scfx_rep.cc (13322:7391057615bd) scfx_rep.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 scfx_rep.cpp -
23
24 Original Author: Robert Graulich, Synopsys, Inc.
25 Martin Janssen, 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: scfx_rep.cpp,v $
41// Revision 1.4 2011/08/24 22:05:43 acg
42// Torsten Maehne: initialization changes to remove warnings.
43//
44// Revision 1.3 2011/08/15 16:43:24 acg
45// Torsten Maehne: changes to remove unused argument warnings.
46//
47// Revision 1.2 2009/02/28 00:26:20 acg
48// Andy Goodrich: bug fixes.
49//
50// Revision 1.2 2008/11/06 17:22:47 acg
51// Andy Goodrich: bug fixes for 2.2.1.
52//
53// Revision 1.1.1.1 2006/12/15 20:31:36 acg
54// SystemC 2.2
55//
56// Revision 1.3 2006/01/13 18:53:58 acg
57// Andy Goodrich: added $Log command so that CVS comments are reproduced in
58// the source.
59//
60
61#include <cctype>
62#include <cmath>
63#include <cstdio>
64#include <cstdlib>
65
66#include "base/compiler.hh"
67#include "systemc/ext/dt/bit/sc_bv_base.hh"
68#include "systemc/ext/dt/bit/sc_lv_base.hh"
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 scfx_rep.cpp -
23
24 Original Author: Robert Graulich, Synopsys, Inc.
25 Martin Janssen, 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: scfx_rep.cpp,v $
41// Revision 1.4 2011/08/24 22:05:43 acg
42// Torsten Maehne: initialization changes to remove warnings.
43//
44// Revision 1.3 2011/08/15 16:43:24 acg
45// Torsten Maehne: changes to remove unused argument warnings.
46//
47// Revision 1.2 2009/02/28 00:26:20 acg
48// Andy Goodrich: bug fixes.
49//
50// Revision 1.2 2008/11/06 17:22:47 acg
51// Andy Goodrich: bug fixes for 2.2.1.
52//
53// Revision 1.1.1.1 2006/12/15 20:31:36 acg
54// SystemC 2.2
55//
56// Revision 1.3 2006/01/13 18:53:58 acg
57// Andy Goodrich: added $Log command so that CVS comments are reproduced in
58// the source.
59//
60
61#include <cctype>
62#include <cmath>
63#include <cstdio>
64#include <cstdlib>
65
66#include "base/compiler.hh"
67#include "systemc/ext/dt/bit/sc_bv_base.hh"
68#include "systemc/ext/dt/bit/sc_lv_base.hh"
69#include "systemc/ext/dt/fx/messages.hh"
69#include "systemc/ext/dt/fx/scfx_ieee.hh"
70#include "systemc/ext/dt/fx/scfx_pow10.hh"
71#include "systemc/ext/dt/fx/scfx_rep.hh"
72#include "systemc/ext/dt/fx/scfx_utils.hh"
73#include "systemc/ext/utils/endian.hh"
74#include "systemc/ext/utils/messages.hh"
75
76namespace sc_dt
77{
78
79// ----------------------------------------------------------------------------
80// some utilities
81// ----------------------------------------------------------------------------
82
83static scfx_pow10 pow10_fx;
84
85static const int mantissa0_size = SCFX_IEEE_DOUBLE_M_SIZE - bits_in_int;
86
87static inline int
88n_word(int x)
89{
90 return (x + bits_in_word - 1) / bits_in_word;
91}
92
93
94// ----------------------------------------------------------------------------
95// CONSTRUCTORS
96// ----------------------------------------------------------------------------
97
98scfx_rep::scfx_rep() :
99 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
100 m_r_flag(false)
101{
102 set_zero();
103}
104
105scfx_rep::scfx_rep(int a) : m_mant(min_mant), m_wp(), m_sign(), m_state(),
106 m_msw(), m_lsw(), m_r_flag(false)
107{
108 if (a != 0) {
109 m_mant.clear();
110 m_wp = m_msw = m_lsw = 2;
111 m_state = normal;
112 if (a > 0) {
113 m_mant[2] = a;
114 m_sign = 1;
115 } else {
116 m_mant[2] = -a;
117 m_sign = -1;
118 }
119 } else {
120 set_zero();
121 }
122}
123
124scfx_rep::scfx_rep(unsigned int a) : m_mant(min_mant), m_wp(), m_sign(),
125 m_state(), m_msw(), m_lsw(), m_r_flag(false)
126{
127 if (a != 0) {
128 m_mant.clear();
129 m_wp = m_msw = m_lsw = 2;
130 m_state = normal;
131 m_mant[2] = a;
132 m_sign = 1;
133 } else {
134 set_zero();
135 }
136}
137
138scfx_rep::scfx_rep(long a) :
139 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
140 m_r_flag(false)
141{
142 if (a != 0) {
143 m_mant.clear();
144 m_state = normal;
145 if (a > 0) {
146 m_sign = 1;
147 } else {
148 a = -a;
149 m_sign = -1;
150 }
151# if SC_LONG_64
152 m_wp = 1;
153 m_mant[1] = static_cast<word>(a);
154 m_mant[2] = static_cast<word>(a >> bits_in_word);
155 find_sw();
156# else
157 m_wp = 2;
158 m_msw = 2;
159 m_lsw = 2;
160 m_mant[2] = a;
161# endif
162 } else {
163 set_zero();
164 }
165}
166
167scfx_rep::scfx_rep(unsigned long a) :
168 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
169 m_r_flag(false)
170{
171 if (a != 0) {
172 m_mant.clear();
173 m_wp = m_msw = m_lsw = 2;
174 m_state = normal;
175# if SC_LONG_64
176 m_wp = 1;
177 m_mant[1] = static_cast<word>(a);
178 m_mant[2] = static_cast<word>(a >> bits_in_word);
179 find_sw();
180# else
181 m_wp = 2;
182 m_msw = 2;
183 m_lsw = 2;
184 m_mant[2] = a;
185# endif
186 m_sign = 1;
187 }
188 else
189 set_zero();
190}
191
192scfx_rep::scfx_rep(double a) :
193 m_mant(min_mant), m_wp(0), m_sign(), m_state(normal), m_msw(0),
194 m_lsw(0), m_r_flag(false)
195{
196 m_mant.clear();
197
198 scfx_ieee_double id(a);
199
200 m_sign = id.negative() ? -1 : 1;
201
202 if (id.is_nan()) {
203 m_state = not_a_number;
204 } else if (id.is_inf()) {
205 m_state = infinity;
206 } else if (id.is_subnormal()) {
207 m_mant[0] = id.mantissa1();
208 m_mant[1] = id.mantissa0();
209 normalize(id.exponent() + 1 - SCFX_IEEE_DOUBLE_M_SIZE);
210 } else if (id.is_normal()) {
211 m_mant[0] = id.mantissa1();
212 m_mant[1] = id.mantissa0() | (1 << mantissa0_size);
213 normalize(id.exponent() - SCFX_IEEE_DOUBLE_M_SIZE);
214 }
215}
216
217scfx_rep::scfx_rep(int64 a) :
218 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
219 m_r_flag(false)
220{
221 if (a != 0) {
222 m_mant.clear();
223 m_wp = 1;
224 m_state = normal;
225 if (a > 0) {
226 m_mant[1] = static_cast<word>(a);
227 m_mant[2] = static_cast<word>(a >> bits_in_word);
228 m_sign = 1;
229 } else {
230 m_mant[1] = static_cast<word>(-a);
231 m_mant[2] = static_cast<word>((-a) >> bits_in_word);
232 m_sign = -1;
233 }
234 find_sw();
235 } else {
236 set_zero();
237 }
238}
239
240scfx_rep::scfx_rep(uint64 a) :
241 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
242 m_r_flag(false)
243{
244 if (a != 0) {
245 m_mant.clear();
246 m_wp = 1;
247 m_state = normal;
248 m_mant[1] = static_cast<word>(a);
249 m_mant[2] = static_cast<word>(a >> bits_in_word);
250 m_sign = 1;
251 find_sw();
252 } else {
253 set_zero();
254 }
255}
256
257scfx_rep::scfx_rep(const sc_signed &a) :
258 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
259 m_r_flag(false)
260{
261 if (a.iszero()) {
262 set_zero();
263 } else {
264 int words = n_word(a.length());
265 if (words > size())
266 resize_to(words);
267 m_mant.clear();
268 m_wp = 0;
269 m_state = normal;
270 if (a.sign()) {
271 sc_signed a2 = -a;
272 for (int i = 0; i < a2.length(); ++i) {
273 if (a2[i]) {
274 scfx_index x = calc_indices(i);
275 m_mant[x.wi()] |= 1 << x.bi();
276 }
277 }
278 m_sign = -1;
279 } else {
280 for (int i = 0; i < a.length(); ++i) {
281 if (a[i]) {
282 scfx_index x = calc_indices(i);
283 m_mant[x.wi()] |= 1 << x.bi();
284 }
285 }
286 m_sign = 1;
287 }
288 find_sw();
289 }
290}
291
292scfx_rep::scfx_rep(const sc_unsigned &a) :
293 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
294 m_r_flag(false)
295{
296 if (a.iszero()) {
297 set_zero();
298 } else {
299 int words = n_word(a.length());
300 if (words > size())
301 resize_to(words);
302 m_mant.clear();
303 m_wp = 0;
304 m_state = normal;
305 for (int i = 0; i < a.length(); ++i) {
306 if (a[i]) {
307 scfx_index x = calc_indices(i);
308 m_mant[x.wi()] |= 1 << x.bi();
309 }
310 }
311 m_sign = 1;
312 find_sw();
313 }
314}
315
316// copy constructor
317scfx_rep::scfx_rep(const scfx_rep &a) :
318 m_mant(a.m_mant), m_wp(a.m_wp), m_sign(a.m_sign), m_state(a.m_state),
319 m_msw(a.m_msw), m_lsw(a.m_lsw), m_r_flag(false)
320{}
321
322
323// ----------------------------------------------------------------------------
324// OPERATORS : new, delete
325//
326// Memory management for class scfx_rep.
327// ----------------------------------------------------------------------------
328
329union scfx_rep_node
330{
331 char data[sizeof(scfx_rep)];
332 scfx_rep_node *next;
333};
334
335static scfx_rep_node *list = 0;
336
337void *
338scfx_rep::operator new(std::size_t size)
339{
340 const int ALLOC_SIZE = 1024;
341
342 if (size != sizeof(scfx_rep))
343 return ::operator new(size);
344
345 if (!list) {
346 list = new scfx_rep_node[ALLOC_SIZE];
347 for (int i = 0; i < ALLOC_SIZE - 1; i++)
348 list[i].next = list + i + 1;
349 list[ALLOC_SIZE - 1].next = 0;
350 }
351
352 scfx_rep *ptr = reinterpret_cast<scfx_rep *>(list->data);
353 list = list->next;
354
355 return ptr;
356}
357
358void
359scfx_rep::operator delete(void *ptr, std::size_t size)
360{
361 if (size != sizeof(scfx_rep)) {
362 ::operator delete(ptr);
363 return;
364 }
365
366 scfx_rep_node *node = static_cast<scfx_rep_node *>(ptr);
367 node->next = list;
368 list = node;
369}
370
371
372// ----------------------------------------------------------------------------
373// METHOD : from_string
374//
375// Convert from character string to sc_fxrep.
376// ----------------------------------------------------------------------------
377
378#define SCFX_FAIL_IF_(cnd) \
379{ \
380 if ((cnd)) { \
381 m_state = not_a_number; \
382 m_mant.clear(); /* to avoid Purify UMRs during assignment */ \
383 return; \
384 } \
385}
386
387void
388scfx_rep::from_string(const char *s, int cte_wl)
389{
390 SCFX_FAIL_IF_(s == 0 || *s == 0);
391
392 scfx_string s2;
393 s2 += s;
394 s2 += '\0';
395
396 bool sign_char;
397 m_sign = scfx_parse_sign(s, sign_char);
398
399 sc_numrep numrep = scfx_parse_prefix(s);
400
401 int base = 0;
402
403 switch (numrep) {
404 case SC_DEC:
405 {
406 base = 10;
407 if (scfx_is_nan(s)) { // special case: NaN
408 m_state = not_a_number;
409 m_mant.clear(); /* to avoid Purify UMRs during assignment */
410 return;
411 }
412 if (scfx_is_inf(s)) { // special case: Infinity
413 m_state = infinity;
414 m_mant.clear(); /* to avoid Purify UMRs during assignment */
415 return;
416 }
417 break;
418 }
419 case SC_BIN:
420 case SC_BIN_US:
421 {
422 SCFX_FAIL_IF_(sign_char);
423 base = 2;
424 break;
425 }
426
427 case SC_BIN_SM:
428 {
429 base = 2;
430 break;
431 }
432 case SC_OCT:
433 case SC_OCT_US:
434 {
435 SCFX_FAIL_IF_(sign_char);
436 base = 8;
437 break;
438 }
439 case SC_OCT_SM:
440 {
441 base = 8;
442 break;
443 }
444 case SC_HEX:
445 case SC_HEX_US:
446 {
447 SCFX_FAIL_IF_(sign_char);
448 base = 16;
449 break;
450 }
451 case SC_HEX_SM:
452 {
453 base = 16;
454 break;
455 }
456 case SC_CSD:
457 {
458 SCFX_FAIL_IF_(sign_char);
459 base = 2;
460 scfx_csd2tc(s2);
461 s = (const char *)s2 + 4;
462 numrep = SC_BIN;
463 break;
464 }
465 default:
466 ;
467 }
468
469 //
470 // find end of mantissa and count the digits and points
471 //
472
473 const char *end = s;
474 bool based_point = false;
475 int int_digits = 0;
476 int frac_digits = 0;
477
478 while (*end) {
479 if (scfx_exp_start(end))
480 break;
481
482 if (*end == '.') {
483 SCFX_FAIL_IF_(based_point);
484 based_point = true;
485 } else {
486 SCFX_FAIL_IF_(!scfx_is_digit(*end, numrep));
487 if (based_point)
488 frac_digits++;
489 else
490 int_digits++;
491 }
492
493 ++end;
494 }
495
496 SCFX_FAIL_IF_(int_digits == 0 && frac_digits == 0);
497
498 // [ exponent ]
499 int exponent = 0;
500
501 if (*end) {
502 for (const char *e = end + 2; *e; ++e)
503 SCFX_FAIL_IF_(!scfx_is_digit(*e, SC_DEC));
504 exponent = std::atoi(end + 1);
505 }
506
507 //
508 // check if the mantissa is negative
509 //
510 bool mant_is_neg = false;
511 switch (numrep) {
512 case SC_BIN:
513 case SC_OCT:
514 case SC_HEX:
515 {
516 const char *p = s;
517 if (*p == '.')
518 ++p;
519
520 mant_is_neg = (scfx_to_digit(* p, numrep) >= (base >> 1));
521 break;
522 }
523 default:
524 ;
525 }
526
527 //
528 // convert the mantissa
529 //
530
531 switch (base) {
532 case 2:
533 {
534 int bit_offset = exponent % bits_in_word;
535 int word_offset = exponent / bits_in_word;
536
537 int_digits += bit_offset;
538 frac_digits -= bit_offset;
539
540 int words = n_word(int_digits) + n_word(frac_digits);
541 if (words > size())
542 resize_to(words);
543 m_mant.clear();
544
545 int j = n_word(frac_digits) * bits_in_word + int_digits - 1;
546
547 for (; s < end; s++) {
548 switch (*s) {
549 case '1':
550 set_bin(j);
551 M5_FALLTHROUGH;
552 case '0':
553 j--;
554 M5_FALLTHROUGH;
555 case '.':
556 break;
557 default:
558 SCFX_FAIL_IF_(true); // should not happen
559 }
560 }
561
562 m_wp = n_word(frac_digits) - word_offset;
563 break;
564 }
565 case 8:
566 {
567 exponent *= 3;
568 int_digits *= 3;
569 frac_digits *= 3;
570
571 int bit_offset = exponent % bits_in_word;
572 int word_offset = exponent / bits_in_word;
573
574 int_digits += bit_offset;
575 frac_digits -= bit_offset;
576
577 int words = n_word(int_digits) + n_word(frac_digits);
578 if (words > size())
579 resize_to(words);
580 m_mant.clear();
581
582 int j = n_word(frac_digits) * bits_in_word + int_digits - 3;
583
584 for (; s < end; s++) {
585 switch (*s) {
586 case '7': case '6': case '5': case '4':
587 case '3': case '2': case '1':
588 set_oct(j, *s - '0');
589 M5_FALLTHROUGH;
590 case '0':
591 j -= 3;
592 M5_FALLTHROUGH;
593 case '.':
594 break;
595 default:
596 SCFX_FAIL_IF_(true); // should not happen
597 }
598 }
599
600 m_wp = n_word(frac_digits) - word_offset;
601 break;
602 }
603 case 10:
604 {
605 word carry, temp;
606 int length = int_digits + frac_digits;
607 resize_to(sc_max(min_mant, n_word(4 * length)));
608
609 m_mant.clear();
610 m_msw = m_lsw = 0;
611
612 for (; s < end; s++) {
613 switch (*s) {
614 case '9': case '8': case '7': case '6': case '5':
615 case '4': case '3': case '2': case '1': case '0':
616 multiply_by_ten();
617 carry = *s - '0';
618 for (int i = 0; carry && i < m_mant.size(); i++) {
619 temp = m_mant[i];
620 temp += carry;
621 carry = temp < m_mant[i];
622 m_mant[i] = temp;
623 }
624 case '.':
625 break;
626 default:
627 SCFX_FAIL_IF_(true); // should not happen
628 }
629 }
630
631 m_wp = 0;
632 find_sw();
633
634 int denominator = frac_digits - exponent;
635
636 if (denominator) {
637 scfx_rep frac_num = pow10_fx(denominator);
638 scfx_rep *temp_num =
639 div_scfx_rep(const_cast<const scfx_rep &>(*this),
640 frac_num, cte_wl);
641 *this = *temp_num;
642 delete temp_num;
643 }
644
645 break;
646 }
647 case 16:
648 {
649 exponent *= 4;
650 int_digits *= 4;
651 frac_digits *= 4;
652
653 int bit_offset = exponent % bits_in_word;
654 int word_offset = exponent / bits_in_word;
655
656 int_digits += bit_offset;
657 frac_digits -= bit_offset;
658
659 int words = n_word(int_digits) + n_word(frac_digits);
660 if (words > size())
661 resize_to(words);
662 m_mant.clear();
663
664 int j = n_word(frac_digits) * bits_in_word + int_digits - 4;
665
666 for (; s < end; s ++) {
667 switch (*s) {
668 case 'f': case 'e': case 'd': case 'c': case 'b': case 'a':
669 set_hex(j, *s - 'a' + 10);
670 j -= 4;
671 break;
672 case 'F': case 'E': case 'D': case 'C': case 'B': case 'A':
673 set_hex(j, *s - 'A' + 10);
674 j -= 4;
675 break;
676 case '9': case '8': case '7': case '6': case '5':
677 case '4': case '3': case '2': case '1':
678 set_hex(j, *s - '0');
679 M5_FALLTHROUGH;
680 case '0':
681 j -= 4;
682 M5_FALLTHROUGH;
683 case '.':
684 break;
685 default:
686 SCFX_FAIL_IF_(true); // should not happen
687 }
688 }
689
690 m_wp = n_word(frac_digits) - word_offset;
691 break;
692 }
693 }
694
695 m_state = normal;
696 find_sw();
697
698 //
699 // two's complement of mantissa if it is negative
700 //
701 if (mant_is_neg) {
702 m_mant[m_msw] |= ~0U << scfx_find_msb(m_mant[m_msw]);
703 for (int i = m_msw + 1; i < m_mant.size(); ++i)
704 m_mant[i] = static_cast<word>(-1);
705 complement(m_mant, m_mant, m_mant.size());
706 inc(m_mant);
707 m_sign *= -1;
708 find_sw();
709 }
710}
711
712#undef SCFX_FAIL_IF_
713
714// ----------------------------------------------------------------------------
715// METHOD : to_double
716//
717// Convert from scfx_rep to double.
718// ----------------------------------------------------------------------------
719
720double
721scfx_rep::to_double() const
722{
723 scfx_ieee_double id;
724
725 // handle special cases
726 if (is_nan()) {
727 id.set_nan();
728 return id;
729 }
730
731 if (is_inf()) {
732 id.set_inf();
733 id.negative(m_sign < 0);
734 return id;
735 }
736
737 if (is_zero()) {
738 id = 0.;
739 id.negative(m_sign < 0);
740 return id;
741 }
742
743 int msb = scfx_find_msb(m_mant[m_msw]);
744
745 int exp = (m_msw - m_wp) * bits_in_word + msb;
746
747 if (exp > SCFX_IEEE_DOUBLE_E_MAX) {
748 id.set_inf();
749 id.negative(m_sign < 0);
750 return id;
751 }
752
753 if (exp < SCFX_IEEE_DOUBLE_E_MIN -
754 static_cast<int>(SCFX_IEEE_DOUBLE_M_SIZE))
755 {
756 id = 0.;
757 return id;
758 }
759
760 int shift = mantissa0_size - msb;
761
762 unsigned int m0;
763 unsigned int m1 = 0;
764 unsigned int guard = 0;
765
766 if (shift == 0) {
767 m0 = m_mant[m_msw] & ~(1 << mantissa0_size);
768 if (m_msw > m_lsw) {
769 m1 = m_mant[m_msw - 1];
770 if (m_msw - 1 > m_lsw)
771 guard = m_mant[m_msw - 2] >> (bits_in_word - 1);
772 }
773 } else if (shift < 0) {
774 m0 = (m_mant[m_msw] >> -shift) & ~(1 << mantissa0_size);
775 m1 = m_mant[m_msw] << (bits_in_word + shift);
776 if (m_msw > m_lsw) {
777 m1 |= m_mant[m_msw - 1] >> -shift;
778 guard = (m_mant[m_msw - 1] >> (-shift - 1)) & 1;
779 }
780 } else {
781 m0 = (m_mant[m_msw] << shift) & ~(1 << mantissa0_size);
782 if (m_msw > m_lsw) {
783 m0 |= m_mant[m_msw - 1] >> (bits_in_word - shift);
784 m1 = m_mant[m_msw - 1] << shift;
785 if (m_msw - 1 > m_lsw) {
786 m1 |= m_mant[m_msw - 2] >> (bits_in_word - shift);
787 guard = (m_mant[m_msw - 2] >> (bits_in_word - shift - 1)) & 1;
788 }
789 }
790 }
791
792 if (exp < SCFX_IEEE_DOUBLE_E_MIN) {
793 m0 |= (1 << mantissa0_size);
794
795 int subnormal_shift = SCFX_IEEE_DOUBLE_E_MIN - exp;
796
797 if (subnormal_shift < bits_in_word) {
798 m1 = m1 >> subnormal_shift |
799 m0 << (bits_in_word - subnormal_shift);
800 m0 = m0 >> subnormal_shift;
801 } else {
802 m1 = m0 >> (subnormal_shift - bits_in_word);
803 m0 = 0;
804 }
805
806 guard = 0;
807
808 exp = SCFX_IEEE_DOUBLE_E_MIN - 1;
809 }
810
811 id.mantissa0(m0);
812 id.mantissa1(m1);
813 id.exponent(exp);
814 id.negative(m_sign < 0);
815
816 double result = id;
817
818 if (guard != 0)
819 result += m_sign * scfx_pow2(exp - SCFX_IEEE_DOUBLE_M_SIZE);
820
821 return result;
822}
823
824
825// ----------------------------------------------------------------------------
826// METHOD : to_uint64
827//
828// Convert from scfx_rep to uint64.
829// Truncates towards 0 _then_ wraps; infinities and NaN go to zero.
830// ----------------------------------------------------------------------------
831
832uint64
833scfx_rep::to_uint64() const
834{
835 if (!is_normal() || is_zero()) {
836 return 0;
837 }
838
839 uint64 result = 0;
840 int shift = 0;
841 int idx = m_wp;
842
843 // Ignore bits off the top; they modulo out.
844 // Ignore bits off the bottom; we're truncating.
845 while (shift < 64 && m_msw >= idx && idx >= m_lsw) {
846 result += static_cast<uint64>(m_mant[idx]) << shift;
847 shift += bits_in_word;
848 idx += 1;
849 }
850
851 return m_sign > 0 ? result : -result;
852}
853
854
855// ----------------------------------------------------------------------------
856// METHOD : to_string
857//
858// Convert from scfx_rep to character string.
859// ----------------------------------------------------------------------------
860
861void
862print_dec(scfx_string &s, const scfx_rep &num, int w_prefix, sc_fmt fmt)
863{
864 if (num.is_neg())
865 s += '-';
866
867 if (w_prefix == 1) {
868 scfx_print_prefix(s, SC_DEC);
869 }
870
871 if (num.is_zero()) {
872 s += '0';
873 return;
874 }
875
876 // split 'num' into its integer and fractional part
877 scfx_rep int_part = num;
878 scfx_rep frac_part = num;
879
880 int i;
881
882 for (i = int_part.m_lsw; i <= int_part.m_msw && i < int_part.m_wp; i++)
883 int_part.m_mant[i] = 0;
884 int_part.find_sw();
885 if (int_part.m_wp < int_part.m_lsw)
886 int_part.resize_to(int_part.size() - int_part.m_wp, -1);
887
888 for (i = frac_part.m_msw;
889 i >= frac_part.m_lsw && i >= frac_part.m_wp; i--)
890 frac_part.m_mant[i] = 0;
891 frac_part.find_sw();
892 if (frac_part.m_msw == frac_part.size() - 1)
893 frac_part.resize_to(frac_part.size() + 1, 1);
894
895 // print integer part
896 int int_digits = 0;
897 int int_zeros = 0;
898
899 if (!int_part.is_zero()) {
900 double int_wl = (int_part.m_msw - int_part.m_wp) * bits_in_word +
901 scfx_find_msb(int_part.m_mant[int_part.m_msw]) + 1;
902 int_digits = (int)std::ceil(int_wl * std::log10(2.));
903
904 int len = s.length();
905 s.append(int_digits);
906
907 bool zero_digits = (frac_part.is_zero() && fmt != SC_F);
908
909 for (i = int_digits + len - 1; i >= len; i--) {
910 unsigned int remainder = int_part.divide_by_ten();
911 s[i] = static_cast<char>('0' + remainder);
912
913 if (zero_digits) {
914 if (remainder == 0)
915 int_zeros++;
916 else
917 zero_digits = false;
918 }
919 }
920
921 // discard trailing zeros from int_part
922 s.discard(int_zeros);
923
924 if (s[len] == '0') {
925 // int_digits was overestimated by one
926 s.remove(len);
927 --int_digits;
928 }
929 }
930
931 // print fractional part
932 int frac_digits = 0;
933 int frac_zeros = 0;
934
935 if (!frac_part.is_zero()) {
936 s += '.';
937
938 bool zero_digits = (int_digits == 0 && fmt != SC_F);
939
940 double frac_wl = (frac_part.m_wp - frac_part.m_msw) * bits_in_word -
941 scfx_find_msb(frac_part.m_mant[frac_part.m_msw]) - 1;
942 frac_zeros = (int)std::floor(frac_wl * std::log10(2.));
943
944 scfx_rep temp;
945 sc_dt::multiply(temp, frac_part, pow10_fx(frac_zeros));
946 frac_part = temp;
947 if (frac_part.m_msw == frac_part.size() - 1)
948 frac_part.resize_to(frac_part.size() + 1, 1);
949
950 frac_digits = frac_zeros;
951 if (!zero_digits) {
952 for (i = 0; i < frac_zeros; i++)
953 s += '0';
954 frac_zeros = 0;
955 }
956
957 while (!frac_part.is_zero()) {
958 frac_part.multiply_by_ten();
959 int n = frac_part.m_mant[frac_part.m_msw + 1];
960
961 if (zero_digits) {
962 if (n == 0)
963 frac_zeros++;
964 else
965 zero_digits = false;
966 }
967
968 if (! zero_digits)
969 s += static_cast<char>('0' + n);
970
971 frac_part.m_mant[frac_part.m_msw + 1] = 0;
972 frac_digits++;
973 }
974 }
975
976 // print exponent
977 if (fmt != SC_F) {
978 if (frac_digits == 0)
979 scfx_print_exp(s, int_zeros);
980 else if (int_digits == 0)
981 scfx_print_exp(s, -frac_zeros);
982 }
983}
984
985void
986print_other(scfx_string &s, const scfx_rep &a, sc_numrep numrep, int w_prefix,
987 sc_fmt fmt, const scfx_params *params)
988{
989 scfx_rep b = a;
990
991 sc_numrep numrep2 = numrep;
992
993 bool numrep_is_sm = (numrep == SC_BIN_SM ||
994 numrep == SC_OCT_SM ||
995 numrep == SC_HEX_SM);
996
997 if (numrep_is_sm) {
998 if (b.is_neg()) {
999 s += '-';
1000 b = *neg_scfx_rep(a);
1001 }
1002 switch (numrep) {
1003 case SC_BIN_SM:
1004 numrep2 = SC_BIN_US;
1005 break;
1006 case SC_OCT_SM:
1007 numrep2 = SC_OCT_US;
1008 break;
1009 case SC_HEX_SM:
1010 numrep2 = SC_HEX_US;
1011 break;
1012 default:
1013 ;
1014 }
1015 }
1016
1017 if (w_prefix != 0) {
1018 scfx_print_prefix(s, numrep);
1019 }
1020
1021 numrep = numrep2;
1022
1023 int msb, lsb;
1024
1025 if (params != 0) {
1026 msb = params->iwl() - 1;
1027 lsb = params->iwl() - params->wl();
1028
1029 if (params->enc() == SC_TC_ &&
1030 (numrep == SC_BIN_US ||
1031 numrep == SC_OCT_US ||
1032 numrep == SC_HEX_US) &&
1033 !numrep_is_sm &&
1034 params->wl() > 1) {
1035 --msb;
1036 } else if (params->enc() == SC_US_ &&
1037 (numrep == SC_BIN ||
1038 numrep == SC_OCT ||
1039 numrep == SC_HEX ||
1040 numrep == SC_CSD)) {
1041 ++msb;
1042 }
1043 } else {
1044 if (b.is_zero()) {
1045 msb = 0;
1046 lsb = 0;
1047 } else {
1048 msb = (b.m_msw - b.m_wp) * bits_in_word
1049 + scfx_find_msb(b.m_mant[ b.m_msw ]) + 1;
1050 while (b.get_bit(msb) == b.get_bit(msb - 1))
1051 --msb;
1052
1053 if (numrep == SC_BIN_US ||
1054 numrep == SC_OCT_US ||
1055 numrep == SC_HEX_US) {
1056 --msb;
1057 }
1058
1059 lsb = (b.m_lsw - b.m_wp) * bits_in_word +
1060 scfx_find_lsb(b.m_mant[b.m_lsw]);
1061
1062 }
1063 }
1064
1065 int step;
1066
1067 switch (numrep) {
1068 case SC_BIN:
1069 case SC_BIN_US:
1070 case SC_CSD:
1071 step = 1;
1072 break;
1073 case SC_OCT:
1074 case SC_OCT_US:
1075 step = 3;
1076 break;
1077 case SC_HEX:
1078 case SC_HEX_US:
1079 step = 4;
1080 break;
1081 default:
1082 SC_REPORT_FATAL(sc_core::SC_ID_ASSERTION_FAILED_,
1083 "unexpected sc_numrep");
1084 sc_core::sc_abort();
1085 }
1086
1087 msb = (int)std::ceil(double(msb + 1) / step) * step - 1;
1088
1089 lsb = (int)std::floor(double(lsb) / step) * step;
1090
1091 if (msb < 0) {
1092 s += '.';
1093 if (fmt == SC_F) {
1094 int sign = (b.is_neg()) ? (1 << step) - 1 : 0;
1095 for (int i = (msb + 1) / step; i < 0; i++) {
1096 if (sign < 10)
1097 s += static_cast<char>(sign + '0');
1098 else
1099 s += static_cast<char>(sign + 'a' - 10);
1100 }
1101 }
1102 }
1103
1104 int i = msb;
1105 while (i >= lsb) {
1106 int value = 0;
1107 for (int j = step - 1; j >= 0; --j) {
1108 value += static_cast<int>(b.get_bit(i)) << j;
1109 --i;
1110 }
1111 if (value < 10)
1112 s += static_cast<char>(value + '0');
1113 else
1114 s += static_cast<char>(value + 'a' - 10);
1115 if (i == -1)
1116 s += '.';
1117 }
1118
1119 if (lsb > 0 && fmt == SC_F) {
1120 for (int i = lsb / step; i > 0; i--)
1121 s += '0';
1122 }
1123
1124 if (s[s.length() - 1] == '.')
1125 s.discard(1);
1126
1127 if (fmt != SC_F) {
1128 if (msb < 0)
1129 scfx_print_exp(s, (msb + 1) / step);
1130 else if (lsb > 0)
1131 scfx_print_exp(s, lsb / step);
1132 }
1133
1134 if (numrep == SC_CSD)
1135 scfx_tc2csd(s, w_prefix);
1136}
1137
1138const char *
1139scfx_rep::to_string(sc_numrep numrep, int w_prefix,
1140 sc_fmt fmt, const scfx_params *params) const
1141{
1142 static scfx_string s;
1143
1144 s.clear();
1145
1146 if (is_nan()) {
1147 scfx_print_nan(s);
1148 } else if (is_inf()) {
1149 scfx_print_inf(s, is_neg());
1150 } else if (is_neg() && !is_zero() &&
1151 (numrep == SC_BIN_US ||
1152 numrep == SC_OCT_US ||
1153 numrep == SC_HEX_US)) {
1154 s += "negative";
1155 } else if (numrep == SC_DEC || numrep == SC_NOBASE) {
1156 sc_dt::print_dec(s, *this, w_prefix, fmt);
1157 } else {
1158 sc_dt::print_other(s, *this, numrep, w_prefix, fmt, params);
1159 }
1160
1161 return s;
1162}
1163
1164
1165// ----------------------------------------------------------------------------
1166// ADD
1167//
1168// add two mantissas of the same size
1169// result has the same size
1170// returns carry of operation
1171// ----------------------------------------------------------------------------
1172
1173static inline int
1174add_mants(int size, scfx_mant &result, const scfx_mant &a, const scfx_mant &b)
1175{
1176 unsigned int carry = 0;
1177
1178 int index = 0;
1179
1180 do {
1181 word x = a[index];
1182 word y = b[index];
1183
1184 y += carry;
1185 carry = y < carry;
1186 y += x;
1187 carry += y < x;
1188 result[index] = y;
1189 } while (++index < size);
1190
1191 return (carry ? 1 : 0);
1192}
1193
1194static inline int
1195sub_mants(int size, scfx_mant &result, const scfx_mant &a, const scfx_mant &b)
1196{
1197 unsigned carry = 0;
1198
1199 int index = 0;
1200
1201 do {
1202 word x = a[index];
1203 word y = b[index];
1204
1205 y += carry;
1206 carry = y < carry;
1207 y = x - y;
1208 carry += y > x;
1209 result[index] = y;
1210 } while (++index < size);
1211
1212 return (carry ? 1 : 0);
1213}
1214
1215scfx_rep *
1216add_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int max_wl)
1217{
1218 scfx_rep &result = *new scfx_rep;
1219
1220 //
1221 // check for special cases
1222 //
1223 if (lhs.is_nan() || rhs.is_nan() ||
1224 (lhs.is_inf() && rhs.is_inf() && lhs.m_sign != rhs.m_sign)) {
1225 result.set_nan();
1226 return &result;
1227 }
1228
1229 if (lhs.is_inf()) {
1230 result.set_inf(lhs.m_sign);
1231 return &result;
1232 }
1233
1234 if (rhs.is_inf()) {
1235 result.set_inf(rhs.m_sign);
1236 return &result;
1237 }
1238
1239 //
1240 // align operands if needed
1241 //
1242 scfx_mant_ref lhs_mant;
1243 scfx_mant_ref rhs_mant;
1244
1245 int len_mant = lhs.size();
1246 int new_wp = lhs.m_wp;
1247
1248 align(lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant);
1249
1250 //
1251 // size the result mantissa
1252 //
1253 result.resize_to(len_mant);
1254 result.m_wp = new_wp;
1255
1256 //
1257 // do it
1258 //
1259 if (lhs.m_sign == rhs.m_sign) {
1260 add_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
1261 result.m_sign = lhs.m_sign;
1262 } else {
1263 int cmp = compare_abs(lhs, rhs);
1264
1265 if (cmp == 1) {
1266 sub_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
1267 result.m_sign = lhs.m_sign;
1268 } else if (cmp == -1) {
1269 sub_mants(len_mant, result.m_mant, rhs_mant, lhs_mant);
1270 result.m_sign = rhs.m_sign;
1271 } else {
1272 result.m_mant.clear();
1273 result.m_sign = 1;
1274 }
1275 }
1276
1277 result.find_sw();
1278 result.round(max_wl);
1279
1280 return &result;
1281}
1282
1283
1284// ----------------------------------------------------------------------------
1285// SUB
1286//
1287// sub two word's of the same size
1288// result has the same size
1289// returns carry of operation
1290// ----------------------------------------------------------------------------
1291
1292static inline int
1293sub_with_index(scfx_mant &a, int a_msw, int /*a_lsw*/,
1294 const scfx_mant &b, int b_msw, int b_lsw)
1295{
1296 unsigned carry = 0;
1297
1298 int size = b_msw - b_lsw;
1299 int a_index = a_msw - size;
1300 int b_index = b_msw - size;
1301
1302 do {
1303 word x = a[a_index];
1304 word y = b[b_index];
1305
1306 y += carry;
1307 carry = y < carry;
1308 y = x - y;
1309 carry += y > x;
1310 a[a_index] = y;
1311
1312 a_index++;
1313 b_index++;
1314 } while (size--);
1315
1316 if (carry) {
1317 // special case: a[a_msw + 1] == 1
1318 a[a_msw + 1] = 0;
1319 }
1320
1321 return (carry ? 1 : 0);
1322}
1323
1324scfx_rep *
1325sub_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int max_wl)
1326{
1327 scfx_rep &result = *new scfx_rep;
1328
1329 //
1330 // check for special cases
1331 //
1332 if (lhs.is_nan() || rhs.is_nan() ||
1333 (lhs.is_inf() && rhs.is_inf() && lhs.m_sign == rhs.m_sign)) {
1334 result.set_nan();
1335 return &result;
1336 }
1337
1338 if (lhs.is_inf()) {
1339 result.set_inf(lhs.m_sign);
1340 return &result;
1341 }
1342
1343 if (rhs.is_inf()) {
1344 result.set_inf(-1 * rhs.m_sign);
1345 return &result;
1346 }
1347
1348 //
1349 // align operands if needed
1350 //
1351 scfx_mant_ref lhs_mant;
1352 scfx_mant_ref rhs_mant;
1353
1354 int len_mant = lhs.size();
1355 int new_wp = lhs.m_wp;
1356
1357 align(lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant);
1358
1359 //
1360 // size the result mantissa
1361 //
1362 result.resize_to(len_mant);
1363 result.m_wp = new_wp;
1364
1365 //
1366 // do it
1367 //
1368 if (lhs.m_sign != rhs.m_sign) {
1369 add_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
1370 result.m_sign = lhs.m_sign;
1371 } else {
1372 int cmp = compare_abs(lhs, rhs);
1373
1374 if (cmp == 1) {
1375 sub_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
1376 result.m_sign = lhs.m_sign;
1377 } else if (cmp == -1) {
1378 sub_mants(len_mant, result.m_mant, rhs_mant, lhs_mant);
1379 result.m_sign = -rhs.m_sign;
1380 } else {
1381 result.m_mant.clear();
1382 result.m_sign = 1;
1383 }
1384 }
1385
1386 result.find_sw();
1387 result.round(max_wl);
1388
1389 return &result;
1390}
1391
1392
1393// ----------------------------------------------------------------------------
1394// MUL
1395// ----------------------------------------------------------------------------
1396
1397union word_short
1398{
1399 word l;
1400 struct
1401 {
1402#if defined(SC_BOOST_BIG_ENDIAN)
1403 half_word u;
1404 half_word l;
1405#elif defined(SC_BOOST_LITTLE_ENDIAN)
1406 half_word l;
1407 half_word u;
1408#endif
1409 } s;
1410};
1411
1412#if defined(SC_BOOST_BIG_ENDIAN)
1413static const int half_word_incr = -1;
1414#elif defined(SC_BOOST_LITTLE_ENDIAN)
1415static const int half_word_incr = 1;
1416#endif
1417
1418void
1419multiply(scfx_rep &result, const scfx_rep &lhs, const scfx_rep &rhs,
1420 int max_wl)
1421{
1422 //
1423 // check for special cases
1424 //
1425 if (lhs.is_nan() || rhs.is_nan() ||
1426 (lhs.is_inf() && rhs.is_zero()) ||
1427 (lhs.is_zero() && rhs.is_inf())) {
1428 result.set_nan();
1429 return;
1430 }
1431
1432 if (lhs.is_inf() || rhs.is_inf()) {
1433 result.set_inf(lhs.m_sign * rhs.m_sign);
1434 return;
1435 }
1436
1437 if (lhs.is_zero() || rhs.is_zero()) {
1438 result.set_zero(lhs.m_sign * rhs.m_sign);
1439 return;
1440 }
1441
1442 //
1443 // do it
1444 //
1445 int len_lhs = lhs.m_msw - lhs.m_lsw + 1;
1446 int len_rhs = rhs.m_msw - rhs.m_lsw + 1;
1447
1448 int new_size = sc_max(min_mant, len_lhs + len_rhs);
1449 int new_wp = (lhs.m_wp - lhs.m_lsw) + (rhs.m_wp - rhs.m_lsw);
1450 int new_sign = lhs.m_sign * rhs.m_sign;
1451
1452 result.resize_to(new_size);
1453 result.m_mant.clear();
1454 result.m_wp = new_wp;
1455 result.m_sign = new_sign;
1456 result.m_state = scfx_rep::normal;
1457
1458 half_word *s1 = lhs.m_mant.half_addr(lhs.m_lsw);
1459 half_word *s2 = rhs.m_mant.half_addr(rhs.m_lsw);
1460
1461 half_word *t = result.m_mant.half_addr();
1462
1463 len_lhs <<= 1;
1464 len_rhs <<= 1;
1465
1466 int i1, i2;
1467
1468 for (i1 = 0; i1 * half_word_incr < len_lhs; i1 += half_word_incr) {
1469 word_short ls;
1470 ls.l = 0;
1471
1472 half_word v1 = s1[i1];
1473
1474 for (i2 = 0; i2 * half_word_incr < len_rhs; i2 += half_word_incr) {
1475 ls.l += v1 * s2[i2];
1476 ls.s.l = ls.s.u + ((t[i2] += ls.s.l) < ls.s.l);
1477 ls.s.u = 0;
1478 }
1479
1480 t[i2] = ls.s.l;
1481 t += half_word_incr;
1482 }
1483
1484 result.find_sw();
1485 result.round(max_wl);
1486}
1487
1488
1489// ----------------------------------------------------------------------------
1490// DIV
1491// ----------------------------------------------------------------------------
1492
1493scfx_rep *
1494div_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int div_wl)
1495{
1496 scfx_rep &result = *new scfx_rep;
1497
1498 //
1499 // check for special cases
1500 //
1501 if (lhs.is_nan() || rhs.is_nan() || (lhs.is_inf() && rhs.is_inf()) ||
1502 (lhs.is_zero() && rhs.is_zero())) {
1503 result.set_nan();
1504 return &result;
1505 }
1506
1507 if (lhs.is_inf() || rhs.is_zero()) {
1508 result.set_inf(lhs.m_sign * rhs.m_sign);
1509 return &result;
1510 }
1511
1512 if (lhs.is_zero() || rhs.is_inf()) {
1513 result.set_zero(lhs.m_sign * rhs.m_sign);
1514 return &result;
1515 }
1516
1517 //
1518 // do it
1519 //
1520
1521 // compute one bit more for rounding
1522 div_wl++;
1523
1524 result.resize_to(sc_max(n_word(div_wl) + 1, min_mant));
1525 result.m_mant.clear();
1526 result.m_sign = lhs.m_sign * rhs.m_sign;
1527
1528 int msb_lhs = scfx_find_msb(lhs.m_mant[lhs.m_msw]) +
1529 (lhs.m_msw - lhs.m_wp) * bits_in_word;
1530 int msb_rhs = scfx_find_msb(rhs.m_mant[rhs.m_msw]) +
1531 (rhs.m_msw - rhs.m_wp) * bits_in_word;
1532
1533 int msb_res = msb_lhs - msb_rhs;
1534 int to_shift = -msb_res % bits_in_word;
1535 int result_index;
1536
1537 int c = (msb_res % bits_in_word >= 0) ? 1 : 0;
1538
1539 result_index = (result.size() - c) * bits_in_word + msb_res % bits_in_word;
1540 result.m_wp = (result.size() - c) - msb_res / bits_in_word;
1541
1542 scfx_rep remainder = lhs;
1543
1544 // align msb from remainder to msb from rhs
1545 remainder.lshift(to_shift);
1546
1547 // make sure msw(remainder) < size - 1
1548 if (remainder.m_msw == remainder.size() - 1)
1549 remainder.resize_to(remainder.size() + 1, 1);
1550
1551 // make sure msw(remainder) >= msw(rhs)!
1552 int msw_diff = rhs.m_msw - remainder.m_msw;
1553 if (msw_diff > 0)
1554 remainder.resize_to(remainder.size() + msw_diff, -1);
1555
1556 int counter;
1557
1558 for (counter = div_wl; counter && !remainder.is_zero(); counter--) {
1559 if (compare_msw_ff(rhs, remainder) <= 0) {
1560 result.set_bin(result_index);
1561 sub_with_index(remainder.m_mant, remainder.m_msw, remainder.m_lsw,
1562 rhs.m_mant, rhs.m_msw, rhs.m_lsw);
1563 }
1564 result_index--;
1565 remainder.shift_left(1);
1566 remainder.m_lsw = remainder.find_lsw();
1567 }
1568
1569 // perform convergent rounding, if needed
1570 if (counter == 0) {
1571 int index = result_index + 1 - result.m_wp * bits_in_word;
1572
1573 scfx_index x = result.calc_indices(index);
1574 scfx_index x1 = result.calc_indices(index + 1);
1575
1576 if (result.o_bit_at(x) && result.o_bit_at(x1))
1577 result.q_incr(x);
1578
1579 result.m_r_flag = true;
1580 }
1581
1582 result.find_sw();
1583
1584 return &result;
1585}
1586
1587// ----------------------------------------------------------------------------
1588// destructive shift mantissa to the left
1589// ----------------------------------------------------------------------------
1590
1591void
1592scfx_rep::lshift(int n)
1593{
1594 if (n == 0)
1595 return;
1596
1597 if (n < 0) {
1598 rshift(-n);
1599 return;
1600 }
1601
1602 if (is_normal()) {
1603 int shift_bits = n % bits_in_word;
1604 int shift_words = n / bits_in_word;
1605
1606 // resize if needed
1607 if (m_msw == size() - 1 &&
1608 scfx_find_msb(m_mant[m_msw]) >= bits_in_word - shift_bits)
1609 resize_to(size() + 1, 1);
1610
1611 // do it
1612 m_wp -= shift_words;
1613 shift_left(shift_bits);
1614 find_sw();
1615 }
1616}
1617
1618// ----------------------------------------------------------------------------
1619// destructive shift mantissa to the right
1620// ----------------------------------------------------------------------------
1621
1622void
1623scfx_rep::rshift(int n)
1624{
1625 if (n == 0)
1626 return;
1627
1628 if (n < 0) {
1629 lshift(-n);
1630 return;
1631 }
1632
1633 if (is_normal()) {
1634 int shift_bits = n % bits_in_word;
1635 int shift_words = n / bits_in_word;
1636
1637 // resize if needed
1638 if (m_lsw == 0 && scfx_find_lsb(m_mant[m_lsw]) < shift_bits)
1639 resize_to(size() + 1, -1);
1640
1641 // do it
1642 m_wp += shift_words;
1643 shift_right(shift_bits);
1644 find_sw();
1645 }
1646}
1647
1648
1649// ----------------------------------------------------------------------------
1650// FRIEND FUNCTION : compare_abs
1651//
1652// Compares the absolute values of two scfx_reps, excluding the special cases.
1653// ----------------------------------------------------------------------------
1654
1655int
1656compare_abs(const scfx_rep &a, const scfx_rep &b)
1657{
1658 // check for zero
1659 word a_word = a.m_mant[a.m_msw];
1660 word b_word = b.m_mant[b.m_msw];
1661
1662 if (a_word == 0 || b_word == 0) {
1663 if (a_word != 0)
1664 return 1;
1665 if (b_word != 0)
1666 return -1;
1667 return 0;
1668 }
1669
1670 // compare msw index
1671 int a_msw = a.m_msw - a.m_wp;
1672 int b_msw = b.m_msw - b.m_wp;
1673
1674 if (a_msw > b_msw)
1675 return 1;
1676
1677 if (a_msw < b_msw)
1678 return -1;
1679
1680 // compare content
1681 int a_i = a.m_msw;
1682 int b_i = b.m_msw;
1683
1684 while (a_i >= a.m_lsw && b_i >= b.m_lsw) {
1685 a_word = a.m_mant[a_i];
1686 b_word = b.m_mant[b_i];
1687 if (a_word > b_word)
1688 return 1;
1689 if (a_word < b_word)
1690 return -1;
1691 --a_i;
1692 --b_i;
1693 }
1694
1695 bool a_zero = true;
1696 while (a_i >= a.m_lsw) {
1697 a_zero = a_zero && (a.m_mant[a_i] == 0);
1698 --a_i;
1699 }
1700
1701 bool b_zero = true;
1702 while (b_i >= b.m_lsw) {
1703 b_zero = b_zero && (b.m_mant[b_i] == 0);
1704 --b_i;
1705 }
1706
1707 // assertion: a_zero || b_zero
1708
1709 if (!a_zero && b_zero)
1710 return 1;
1711
1712 if (a_zero && !b_zero)
1713 return -1;
1714
1715 return 0;
1716}
1717
1718// ----------------------------------------------------------------------------
1719// FRIEND FUNCTION : cmp_scfx_rep
1720//
1721// Compares the values of two scfx_reps, including the special cases.
1722// ----------------------------------------------------------------------------
1723
1724int
1725cmp_scfx_rep(const scfx_rep &a, const scfx_rep &b)
1726{
1727 // handle special cases
1728
1729 if (a.is_nan() || b.is_nan()) {
1730 return 2;
1731 }
1732
1733 if (a.is_inf() || b.is_inf()) {
1734 if (a.is_inf()) {
1735 if (!a.is_neg()) {
1736 if (b.is_inf() && !b.is_neg()) {
1737 return 0;
1738 } else {
1739 return 1;
1740 }
1741 } else {
1742 if (b.is_inf() && b.is_neg()) {
1743 return 0;
1744 } else {
1745 return -1;
1746 }
1747 }
1748 }
1749 if (b.is_inf()) {
1750 if (!b.is_neg()) {
1751 return -1;
1752 } else {
1753 return 1;
1754 }
1755 }
1756 }
1757
1758 if (a.is_zero() && b.is_zero()) {
1759 return 0;
1760 }
1761
1762 // compare sign
1763 if (a.m_sign != b.m_sign) {
1764 return a.m_sign;
1765 }
1766
1767 return (a.m_sign * compare_abs(a, b));
1768}
1769
1770
1771// ----------------------------------------------------------------------------
1772// PRIVATE METHOD : quantization
1773//
1774// Performs destructive quantization.
1775// ----------------------------------------------------------------------------
1776
1777void
1778scfx_rep::quantization(const scfx_params &params, bool &q_flag)
1779{
1780 scfx_index x = calc_indices(params.iwl() - params.wl());
1781
1782 if (x.wi() < 0)
1783 return;
1784
1785 if (x.wi() >= size())
1786 resize_to(x.wi() + 1, 1);
1787
1788 bool qb = q_bit(x);
1789 bool qz = q_zero(x);
1790
1791 q_flag = (qb || ! qz);
1792
1793 if (q_flag) {
1794 switch (params.q_mode()) {
1795 case SC_TRN: // truncation
1796 {
1797 if (is_neg())
1798 q_incr(x);
1799 break;
1800 }
1801 case SC_RND: // rounding to plus infinity
1802 {
1803 if (!is_neg()) {
1804 if (qb)
1805 q_incr(x);
1806 } else {
1807 if (qb && !qz)
1808 q_incr(x);
1809 }
1810 break;
1811 }
1812 case SC_TRN_ZERO: // truncation to zero
1813 {
1814 break;
1815 }
1816 case SC_RND_INF: // rounding to infinity
1817 {
1818 if (qb)
1819 q_incr(x);
1820 break;
1821 }
1822 case SC_RND_CONV: // convergent rounding
1823 {
1824 if ((qb && !qz) || (qb && qz && q_odd(x)))
1825 q_incr(x);
1826 break;
1827 }
1828 case SC_RND_ZERO: // rounding to zero
1829 {
1830 if (qb && !qz)
1831 q_incr(x);
1832 break;
1833 }
1834 case SC_RND_MIN_INF: // rounding to minus infinity
1835 {
1836 if (!is_neg()) {
1837 if (qb && !qz)
1838 q_incr(x);
1839 } else {
1840 if (qb)
1841 q_incr(x);
1842 }
1843 break;
1844 }
1845 default:
1846 ;
1847 }
1848 q_clear(x);
1849
1850 find_sw();
1851 }
1852}
1853
1854
1855// ----------------------------------------------------------------------------
1856// PRIVATE METHOD : overflow
1857//
1858// Performs destructive overflow handling.
1859// ----------------------------------------------------------------------------
1860
1861void
1862scfx_rep::overflow(const scfx_params &params, bool &o_flag)
1863{
1864 scfx_index x = calc_indices(params.iwl() - 1);
1865
1866 if (x.wi() >= size())
1867 resize_to(x.wi() + 1, 1);
1868
1869 if (x.wi() < 0) {
1870 resize_to(size() - x.wi(), -1);
1871 x.wi(0);
1872 }
1873
1874 bool zero_left = o_zero_left(x);
1875 bool bit_at = o_bit_at(x);
1876 bool zero_right = o_zero_right(x);
1877
1878 bool under = false;
1879 bool over = false;
1880
1881 sc_enc enc = params.enc();
1882
1883 if (enc == SC_TC_) {
1884 if (is_neg()) {
1885 if (params.o_mode() == SC_SAT_SYM)
1886 under = (!zero_left || bit_at);
1887 else
1888 under = (!zero_left || (zero_left && bit_at && ! zero_right));
1889 } else {
1890 over = (! zero_left || bit_at);
1891 }
1892 } else {
1893 if (is_neg())
1894 under = (!is_zero());
1895 else
1896 over = (!zero_left);
1897 }
1898
1899 o_flag = (under || over);
1900
1901 if (o_flag) {
1902 scfx_index x2 = calc_indices(params.iwl() - params.wl());
1903
1904 if (x2.wi() < 0) {
1905 resize_to(size() - x2.wi(), -1);
1906 x.wi(x.wi() - x2.wi());
1907 x2.wi(0);
1908 }
1909
1910 switch (params.o_mode()) {
1911 case SC_WRAP: // wrap-around
1912 {
1913 int n_bits = params.n_bits();
1914
1915 if (n_bits == 0) {
1916 // wrap-around all 'wl' bits
1917 toggle_tc();
1918 o_extend(x, enc);
1919 toggle_tc();
1920 } else if (n_bits < params.wl()) {
1921 scfx_index x3 = calc_indices(params.iwl() - 1 - n_bits);
1922
1923 // wrap-around least significant 'wl - n_bits' bits;
1924 // saturate most significant 'n_bits' bits
1925 toggle_tc();
1926 o_set(x, x3, enc, under);
1927 o_extend(x, enc);
1928 toggle_tc();
1929 } else {
1930 // saturate all 'wl' bits
1931 if (under)
1932 o_set_low(x, enc);
1933 else
1934 o_set_high(x, x2, enc);
1935 }
1936 break;
1937 }
1938 case SC_SAT: // saturation
1939 {
1940 if (under)
1941 o_set_low(x, enc);
1942 else
1943 o_set_high(x, x2, enc);
1944 break;
1945 }
1946 case SC_SAT_SYM: // symmetrical saturation
1947 {
1948 if (under) {
1949 if (enc == SC_TC_)
1950 o_set_high(x, x2, SC_TC_, -1);
1951 else
1952 o_set_low(x, SC_US_);
1953 } else {
1954 o_set_high(x, x2, enc);
1955 }
1956 break;
1957 }
1958 case SC_SAT_ZERO: // saturation to zero
1959 {
1960 set_zero();
1961 break;
1962 }
1963 case SC_WRAP_SM: // sign magnitude wrap-around
1964 {
1965 SC_ERROR_IF_(enc == SC_US_,
70#include "systemc/ext/dt/fx/scfx_ieee.hh"
71#include "systemc/ext/dt/fx/scfx_pow10.hh"
72#include "systemc/ext/dt/fx/scfx_rep.hh"
73#include "systemc/ext/dt/fx/scfx_utils.hh"
74#include "systemc/ext/utils/endian.hh"
75#include "systemc/ext/utils/messages.hh"
76
77namespace sc_dt
78{
79
80// ----------------------------------------------------------------------------
81// some utilities
82// ----------------------------------------------------------------------------
83
84static scfx_pow10 pow10_fx;
85
86static const int mantissa0_size = SCFX_IEEE_DOUBLE_M_SIZE - bits_in_int;
87
88static inline int
89n_word(int x)
90{
91 return (x + bits_in_word - 1) / bits_in_word;
92}
93
94
95// ----------------------------------------------------------------------------
96// CONSTRUCTORS
97// ----------------------------------------------------------------------------
98
99scfx_rep::scfx_rep() :
100 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
101 m_r_flag(false)
102{
103 set_zero();
104}
105
106scfx_rep::scfx_rep(int a) : m_mant(min_mant), m_wp(), m_sign(), m_state(),
107 m_msw(), m_lsw(), m_r_flag(false)
108{
109 if (a != 0) {
110 m_mant.clear();
111 m_wp = m_msw = m_lsw = 2;
112 m_state = normal;
113 if (a > 0) {
114 m_mant[2] = a;
115 m_sign = 1;
116 } else {
117 m_mant[2] = -a;
118 m_sign = -1;
119 }
120 } else {
121 set_zero();
122 }
123}
124
125scfx_rep::scfx_rep(unsigned int a) : m_mant(min_mant), m_wp(), m_sign(),
126 m_state(), m_msw(), m_lsw(), m_r_flag(false)
127{
128 if (a != 0) {
129 m_mant.clear();
130 m_wp = m_msw = m_lsw = 2;
131 m_state = normal;
132 m_mant[2] = a;
133 m_sign = 1;
134 } else {
135 set_zero();
136 }
137}
138
139scfx_rep::scfx_rep(long a) :
140 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
141 m_r_flag(false)
142{
143 if (a != 0) {
144 m_mant.clear();
145 m_state = normal;
146 if (a > 0) {
147 m_sign = 1;
148 } else {
149 a = -a;
150 m_sign = -1;
151 }
152# if SC_LONG_64
153 m_wp = 1;
154 m_mant[1] = static_cast<word>(a);
155 m_mant[2] = static_cast<word>(a >> bits_in_word);
156 find_sw();
157# else
158 m_wp = 2;
159 m_msw = 2;
160 m_lsw = 2;
161 m_mant[2] = a;
162# endif
163 } else {
164 set_zero();
165 }
166}
167
168scfx_rep::scfx_rep(unsigned long a) :
169 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
170 m_r_flag(false)
171{
172 if (a != 0) {
173 m_mant.clear();
174 m_wp = m_msw = m_lsw = 2;
175 m_state = normal;
176# if SC_LONG_64
177 m_wp = 1;
178 m_mant[1] = static_cast<word>(a);
179 m_mant[2] = static_cast<word>(a >> bits_in_word);
180 find_sw();
181# else
182 m_wp = 2;
183 m_msw = 2;
184 m_lsw = 2;
185 m_mant[2] = a;
186# endif
187 m_sign = 1;
188 }
189 else
190 set_zero();
191}
192
193scfx_rep::scfx_rep(double a) :
194 m_mant(min_mant), m_wp(0), m_sign(), m_state(normal), m_msw(0),
195 m_lsw(0), m_r_flag(false)
196{
197 m_mant.clear();
198
199 scfx_ieee_double id(a);
200
201 m_sign = id.negative() ? -1 : 1;
202
203 if (id.is_nan()) {
204 m_state = not_a_number;
205 } else if (id.is_inf()) {
206 m_state = infinity;
207 } else if (id.is_subnormal()) {
208 m_mant[0] = id.mantissa1();
209 m_mant[1] = id.mantissa0();
210 normalize(id.exponent() + 1 - SCFX_IEEE_DOUBLE_M_SIZE);
211 } else if (id.is_normal()) {
212 m_mant[0] = id.mantissa1();
213 m_mant[1] = id.mantissa0() | (1 << mantissa0_size);
214 normalize(id.exponent() - SCFX_IEEE_DOUBLE_M_SIZE);
215 }
216}
217
218scfx_rep::scfx_rep(int64 a) :
219 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
220 m_r_flag(false)
221{
222 if (a != 0) {
223 m_mant.clear();
224 m_wp = 1;
225 m_state = normal;
226 if (a > 0) {
227 m_mant[1] = static_cast<word>(a);
228 m_mant[2] = static_cast<word>(a >> bits_in_word);
229 m_sign = 1;
230 } else {
231 m_mant[1] = static_cast<word>(-a);
232 m_mant[2] = static_cast<word>((-a) >> bits_in_word);
233 m_sign = -1;
234 }
235 find_sw();
236 } else {
237 set_zero();
238 }
239}
240
241scfx_rep::scfx_rep(uint64 a) :
242 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
243 m_r_flag(false)
244{
245 if (a != 0) {
246 m_mant.clear();
247 m_wp = 1;
248 m_state = normal;
249 m_mant[1] = static_cast<word>(a);
250 m_mant[2] = static_cast<word>(a >> bits_in_word);
251 m_sign = 1;
252 find_sw();
253 } else {
254 set_zero();
255 }
256}
257
258scfx_rep::scfx_rep(const sc_signed &a) :
259 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
260 m_r_flag(false)
261{
262 if (a.iszero()) {
263 set_zero();
264 } else {
265 int words = n_word(a.length());
266 if (words > size())
267 resize_to(words);
268 m_mant.clear();
269 m_wp = 0;
270 m_state = normal;
271 if (a.sign()) {
272 sc_signed a2 = -a;
273 for (int i = 0; i < a2.length(); ++i) {
274 if (a2[i]) {
275 scfx_index x = calc_indices(i);
276 m_mant[x.wi()] |= 1 << x.bi();
277 }
278 }
279 m_sign = -1;
280 } else {
281 for (int i = 0; i < a.length(); ++i) {
282 if (a[i]) {
283 scfx_index x = calc_indices(i);
284 m_mant[x.wi()] |= 1 << x.bi();
285 }
286 }
287 m_sign = 1;
288 }
289 find_sw();
290 }
291}
292
293scfx_rep::scfx_rep(const sc_unsigned &a) :
294 m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
295 m_r_flag(false)
296{
297 if (a.iszero()) {
298 set_zero();
299 } else {
300 int words = n_word(a.length());
301 if (words > size())
302 resize_to(words);
303 m_mant.clear();
304 m_wp = 0;
305 m_state = normal;
306 for (int i = 0; i < a.length(); ++i) {
307 if (a[i]) {
308 scfx_index x = calc_indices(i);
309 m_mant[x.wi()] |= 1 << x.bi();
310 }
311 }
312 m_sign = 1;
313 find_sw();
314 }
315}
316
317// copy constructor
318scfx_rep::scfx_rep(const scfx_rep &a) :
319 m_mant(a.m_mant), m_wp(a.m_wp), m_sign(a.m_sign), m_state(a.m_state),
320 m_msw(a.m_msw), m_lsw(a.m_lsw), m_r_flag(false)
321{}
322
323
324// ----------------------------------------------------------------------------
325// OPERATORS : new, delete
326//
327// Memory management for class scfx_rep.
328// ----------------------------------------------------------------------------
329
330union scfx_rep_node
331{
332 char data[sizeof(scfx_rep)];
333 scfx_rep_node *next;
334};
335
336static scfx_rep_node *list = 0;
337
338void *
339scfx_rep::operator new(std::size_t size)
340{
341 const int ALLOC_SIZE = 1024;
342
343 if (size != sizeof(scfx_rep))
344 return ::operator new(size);
345
346 if (!list) {
347 list = new scfx_rep_node[ALLOC_SIZE];
348 for (int i = 0; i < ALLOC_SIZE - 1; i++)
349 list[i].next = list + i + 1;
350 list[ALLOC_SIZE - 1].next = 0;
351 }
352
353 scfx_rep *ptr = reinterpret_cast<scfx_rep *>(list->data);
354 list = list->next;
355
356 return ptr;
357}
358
359void
360scfx_rep::operator delete(void *ptr, std::size_t size)
361{
362 if (size != sizeof(scfx_rep)) {
363 ::operator delete(ptr);
364 return;
365 }
366
367 scfx_rep_node *node = static_cast<scfx_rep_node *>(ptr);
368 node->next = list;
369 list = node;
370}
371
372
373// ----------------------------------------------------------------------------
374// METHOD : from_string
375//
376// Convert from character string to sc_fxrep.
377// ----------------------------------------------------------------------------
378
379#define SCFX_FAIL_IF_(cnd) \
380{ \
381 if ((cnd)) { \
382 m_state = not_a_number; \
383 m_mant.clear(); /* to avoid Purify UMRs during assignment */ \
384 return; \
385 } \
386}
387
388void
389scfx_rep::from_string(const char *s, int cte_wl)
390{
391 SCFX_FAIL_IF_(s == 0 || *s == 0);
392
393 scfx_string s2;
394 s2 += s;
395 s2 += '\0';
396
397 bool sign_char;
398 m_sign = scfx_parse_sign(s, sign_char);
399
400 sc_numrep numrep = scfx_parse_prefix(s);
401
402 int base = 0;
403
404 switch (numrep) {
405 case SC_DEC:
406 {
407 base = 10;
408 if (scfx_is_nan(s)) { // special case: NaN
409 m_state = not_a_number;
410 m_mant.clear(); /* to avoid Purify UMRs during assignment */
411 return;
412 }
413 if (scfx_is_inf(s)) { // special case: Infinity
414 m_state = infinity;
415 m_mant.clear(); /* to avoid Purify UMRs during assignment */
416 return;
417 }
418 break;
419 }
420 case SC_BIN:
421 case SC_BIN_US:
422 {
423 SCFX_FAIL_IF_(sign_char);
424 base = 2;
425 break;
426 }
427
428 case SC_BIN_SM:
429 {
430 base = 2;
431 break;
432 }
433 case SC_OCT:
434 case SC_OCT_US:
435 {
436 SCFX_FAIL_IF_(sign_char);
437 base = 8;
438 break;
439 }
440 case SC_OCT_SM:
441 {
442 base = 8;
443 break;
444 }
445 case SC_HEX:
446 case SC_HEX_US:
447 {
448 SCFX_FAIL_IF_(sign_char);
449 base = 16;
450 break;
451 }
452 case SC_HEX_SM:
453 {
454 base = 16;
455 break;
456 }
457 case SC_CSD:
458 {
459 SCFX_FAIL_IF_(sign_char);
460 base = 2;
461 scfx_csd2tc(s2);
462 s = (const char *)s2 + 4;
463 numrep = SC_BIN;
464 break;
465 }
466 default:
467 ;
468 }
469
470 //
471 // find end of mantissa and count the digits and points
472 //
473
474 const char *end = s;
475 bool based_point = false;
476 int int_digits = 0;
477 int frac_digits = 0;
478
479 while (*end) {
480 if (scfx_exp_start(end))
481 break;
482
483 if (*end == '.') {
484 SCFX_FAIL_IF_(based_point);
485 based_point = true;
486 } else {
487 SCFX_FAIL_IF_(!scfx_is_digit(*end, numrep));
488 if (based_point)
489 frac_digits++;
490 else
491 int_digits++;
492 }
493
494 ++end;
495 }
496
497 SCFX_FAIL_IF_(int_digits == 0 && frac_digits == 0);
498
499 // [ exponent ]
500 int exponent = 0;
501
502 if (*end) {
503 for (const char *e = end + 2; *e; ++e)
504 SCFX_FAIL_IF_(!scfx_is_digit(*e, SC_DEC));
505 exponent = std::atoi(end + 1);
506 }
507
508 //
509 // check if the mantissa is negative
510 //
511 bool mant_is_neg = false;
512 switch (numrep) {
513 case SC_BIN:
514 case SC_OCT:
515 case SC_HEX:
516 {
517 const char *p = s;
518 if (*p == '.')
519 ++p;
520
521 mant_is_neg = (scfx_to_digit(* p, numrep) >= (base >> 1));
522 break;
523 }
524 default:
525 ;
526 }
527
528 //
529 // convert the mantissa
530 //
531
532 switch (base) {
533 case 2:
534 {
535 int bit_offset = exponent % bits_in_word;
536 int word_offset = exponent / bits_in_word;
537
538 int_digits += bit_offset;
539 frac_digits -= bit_offset;
540
541 int words = n_word(int_digits) + n_word(frac_digits);
542 if (words > size())
543 resize_to(words);
544 m_mant.clear();
545
546 int j = n_word(frac_digits) * bits_in_word + int_digits - 1;
547
548 for (; s < end; s++) {
549 switch (*s) {
550 case '1':
551 set_bin(j);
552 M5_FALLTHROUGH;
553 case '0':
554 j--;
555 M5_FALLTHROUGH;
556 case '.':
557 break;
558 default:
559 SCFX_FAIL_IF_(true); // should not happen
560 }
561 }
562
563 m_wp = n_word(frac_digits) - word_offset;
564 break;
565 }
566 case 8:
567 {
568 exponent *= 3;
569 int_digits *= 3;
570 frac_digits *= 3;
571
572 int bit_offset = exponent % bits_in_word;
573 int word_offset = exponent / bits_in_word;
574
575 int_digits += bit_offset;
576 frac_digits -= bit_offset;
577
578 int words = n_word(int_digits) + n_word(frac_digits);
579 if (words > size())
580 resize_to(words);
581 m_mant.clear();
582
583 int j = n_word(frac_digits) * bits_in_word + int_digits - 3;
584
585 for (; s < end; s++) {
586 switch (*s) {
587 case '7': case '6': case '5': case '4':
588 case '3': case '2': case '1':
589 set_oct(j, *s - '0');
590 M5_FALLTHROUGH;
591 case '0':
592 j -= 3;
593 M5_FALLTHROUGH;
594 case '.':
595 break;
596 default:
597 SCFX_FAIL_IF_(true); // should not happen
598 }
599 }
600
601 m_wp = n_word(frac_digits) - word_offset;
602 break;
603 }
604 case 10:
605 {
606 word carry, temp;
607 int length = int_digits + frac_digits;
608 resize_to(sc_max(min_mant, n_word(4 * length)));
609
610 m_mant.clear();
611 m_msw = m_lsw = 0;
612
613 for (; s < end; s++) {
614 switch (*s) {
615 case '9': case '8': case '7': case '6': case '5':
616 case '4': case '3': case '2': case '1': case '0':
617 multiply_by_ten();
618 carry = *s - '0';
619 for (int i = 0; carry && i < m_mant.size(); i++) {
620 temp = m_mant[i];
621 temp += carry;
622 carry = temp < m_mant[i];
623 m_mant[i] = temp;
624 }
625 case '.':
626 break;
627 default:
628 SCFX_FAIL_IF_(true); // should not happen
629 }
630 }
631
632 m_wp = 0;
633 find_sw();
634
635 int denominator = frac_digits - exponent;
636
637 if (denominator) {
638 scfx_rep frac_num = pow10_fx(denominator);
639 scfx_rep *temp_num =
640 div_scfx_rep(const_cast<const scfx_rep &>(*this),
641 frac_num, cte_wl);
642 *this = *temp_num;
643 delete temp_num;
644 }
645
646 break;
647 }
648 case 16:
649 {
650 exponent *= 4;
651 int_digits *= 4;
652 frac_digits *= 4;
653
654 int bit_offset = exponent % bits_in_word;
655 int word_offset = exponent / bits_in_word;
656
657 int_digits += bit_offset;
658 frac_digits -= bit_offset;
659
660 int words = n_word(int_digits) + n_word(frac_digits);
661 if (words > size())
662 resize_to(words);
663 m_mant.clear();
664
665 int j = n_word(frac_digits) * bits_in_word + int_digits - 4;
666
667 for (; s < end; s ++) {
668 switch (*s) {
669 case 'f': case 'e': case 'd': case 'c': case 'b': case 'a':
670 set_hex(j, *s - 'a' + 10);
671 j -= 4;
672 break;
673 case 'F': case 'E': case 'D': case 'C': case 'B': case 'A':
674 set_hex(j, *s - 'A' + 10);
675 j -= 4;
676 break;
677 case '9': case '8': case '7': case '6': case '5':
678 case '4': case '3': case '2': case '1':
679 set_hex(j, *s - '0');
680 M5_FALLTHROUGH;
681 case '0':
682 j -= 4;
683 M5_FALLTHROUGH;
684 case '.':
685 break;
686 default:
687 SCFX_FAIL_IF_(true); // should not happen
688 }
689 }
690
691 m_wp = n_word(frac_digits) - word_offset;
692 break;
693 }
694 }
695
696 m_state = normal;
697 find_sw();
698
699 //
700 // two's complement of mantissa if it is negative
701 //
702 if (mant_is_neg) {
703 m_mant[m_msw] |= ~0U << scfx_find_msb(m_mant[m_msw]);
704 for (int i = m_msw + 1; i < m_mant.size(); ++i)
705 m_mant[i] = static_cast<word>(-1);
706 complement(m_mant, m_mant, m_mant.size());
707 inc(m_mant);
708 m_sign *= -1;
709 find_sw();
710 }
711}
712
713#undef SCFX_FAIL_IF_
714
715// ----------------------------------------------------------------------------
716// METHOD : to_double
717//
718// Convert from scfx_rep to double.
719// ----------------------------------------------------------------------------
720
721double
722scfx_rep::to_double() const
723{
724 scfx_ieee_double id;
725
726 // handle special cases
727 if (is_nan()) {
728 id.set_nan();
729 return id;
730 }
731
732 if (is_inf()) {
733 id.set_inf();
734 id.negative(m_sign < 0);
735 return id;
736 }
737
738 if (is_zero()) {
739 id = 0.;
740 id.negative(m_sign < 0);
741 return id;
742 }
743
744 int msb = scfx_find_msb(m_mant[m_msw]);
745
746 int exp = (m_msw - m_wp) * bits_in_word + msb;
747
748 if (exp > SCFX_IEEE_DOUBLE_E_MAX) {
749 id.set_inf();
750 id.negative(m_sign < 0);
751 return id;
752 }
753
754 if (exp < SCFX_IEEE_DOUBLE_E_MIN -
755 static_cast<int>(SCFX_IEEE_DOUBLE_M_SIZE))
756 {
757 id = 0.;
758 return id;
759 }
760
761 int shift = mantissa0_size - msb;
762
763 unsigned int m0;
764 unsigned int m1 = 0;
765 unsigned int guard = 0;
766
767 if (shift == 0) {
768 m0 = m_mant[m_msw] & ~(1 << mantissa0_size);
769 if (m_msw > m_lsw) {
770 m1 = m_mant[m_msw - 1];
771 if (m_msw - 1 > m_lsw)
772 guard = m_mant[m_msw - 2] >> (bits_in_word - 1);
773 }
774 } else if (shift < 0) {
775 m0 = (m_mant[m_msw] >> -shift) & ~(1 << mantissa0_size);
776 m1 = m_mant[m_msw] << (bits_in_word + shift);
777 if (m_msw > m_lsw) {
778 m1 |= m_mant[m_msw - 1] >> -shift;
779 guard = (m_mant[m_msw - 1] >> (-shift - 1)) & 1;
780 }
781 } else {
782 m0 = (m_mant[m_msw] << shift) & ~(1 << mantissa0_size);
783 if (m_msw > m_lsw) {
784 m0 |= m_mant[m_msw - 1] >> (bits_in_word - shift);
785 m1 = m_mant[m_msw - 1] << shift;
786 if (m_msw - 1 > m_lsw) {
787 m1 |= m_mant[m_msw - 2] >> (bits_in_word - shift);
788 guard = (m_mant[m_msw - 2] >> (bits_in_word - shift - 1)) & 1;
789 }
790 }
791 }
792
793 if (exp < SCFX_IEEE_DOUBLE_E_MIN) {
794 m0 |= (1 << mantissa0_size);
795
796 int subnormal_shift = SCFX_IEEE_DOUBLE_E_MIN - exp;
797
798 if (subnormal_shift < bits_in_word) {
799 m1 = m1 >> subnormal_shift |
800 m0 << (bits_in_word - subnormal_shift);
801 m0 = m0 >> subnormal_shift;
802 } else {
803 m1 = m0 >> (subnormal_shift - bits_in_word);
804 m0 = 0;
805 }
806
807 guard = 0;
808
809 exp = SCFX_IEEE_DOUBLE_E_MIN - 1;
810 }
811
812 id.mantissa0(m0);
813 id.mantissa1(m1);
814 id.exponent(exp);
815 id.negative(m_sign < 0);
816
817 double result = id;
818
819 if (guard != 0)
820 result += m_sign * scfx_pow2(exp - SCFX_IEEE_DOUBLE_M_SIZE);
821
822 return result;
823}
824
825
826// ----------------------------------------------------------------------------
827// METHOD : to_uint64
828//
829// Convert from scfx_rep to uint64.
830// Truncates towards 0 _then_ wraps; infinities and NaN go to zero.
831// ----------------------------------------------------------------------------
832
833uint64
834scfx_rep::to_uint64() const
835{
836 if (!is_normal() || is_zero()) {
837 return 0;
838 }
839
840 uint64 result = 0;
841 int shift = 0;
842 int idx = m_wp;
843
844 // Ignore bits off the top; they modulo out.
845 // Ignore bits off the bottom; we're truncating.
846 while (shift < 64 && m_msw >= idx && idx >= m_lsw) {
847 result += static_cast<uint64>(m_mant[idx]) << shift;
848 shift += bits_in_word;
849 idx += 1;
850 }
851
852 return m_sign > 0 ? result : -result;
853}
854
855
856// ----------------------------------------------------------------------------
857// METHOD : to_string
858//
859// Convert from scfx_rep to character string.
860// ----------------------------------------------------------------------------
861
862void
863print_dec(scfx_string &s, const scfx_rep &num, int w_prefix, sc_fmt fmt)
864{
865 if (num.is_neg())
866 s += '-';
867
868 if (w_prefix == 1) {
869 scfx_print_prefix(s, SC_DEC);
870 }
871
872 if (num.is_zero()) {
873 s += '0';
874 return;
875 }
876
877 // split 'num' into its integer and fractional part
878 scfx_rep int_part = num;
879 scfx_rep frac_part = num;
880
881 int i;
882
883 for (i = int_part.m_lsw; i <= int_part.m_msw && i < int_part.m_wp; i++)
884 int_part.m_mant[i] = 0;
885 int_part.find_sw();
886 if (int_part.m_wp < int_part.m_lsw)
887 int_part.resize_to(int_part.size() - int_part.m_wp, -1);
888
889 for (i = frac_part.m_msw;
890 i >= frac_part.m_lsw && i >= frac_part.m_wp; i--)
891 frac_part.m_mant[i] = 0;
892 frac_part.find_sw();
893 if (frac_part.m_msw == frac_part.size() - 1)
894 frac_part.resize_to(frac_part.size() + 1, 1);
895
896 // print integer part
897 int int_digits = 0;
898 int int_zeros = 0;
899
900 if (!int_part.is_zero()) {
901 double int_wl = (int_part.m_msw - int_part.m_wp) * bits_in_word +
902 scfx_find_msb(int_part.m_mant[int_part.m_msw]) + 1;
903 int_digits = (int)std::ceil(int_wl * std::log10(2.));
904
905 int len = s.length();
906 s.append(int_digits);
907
908 bool zero_digits = (frac_part.is_zero() && fmt != SC_F);
909
910 for (i = int_digits + len - 1; i >= len; i--) {
911 unsigned int remainder = int_part.divide_by_ten();
912 s[i] = static_cast<char>('0' + remainder);
913
914 if (zero_digits) {
915 if (remainder == 0)
916 int_zeros++;
917 else
918 zero_digits = false;
919 }
920 }
921
922 // discard trailing zeros from int_part
923 s.discard(int_zeros);
924
925 if (s[len] == '0') {
926 // int_digits was overestimated by one
927 s.remove(len);
928 --int_digits;
929 }
930 }
931
932 // print fractional part
933 int frac_digits = 0;
934 int frac_zeros = 0;
935
936 if (!frac_part.is_zero()) {
937 s += '.';
938
939 bool zero_digits = (int_digits == 0 && fmt != SC_F);
940
941 double frac_wl = (frac_part.m_wp - frac_part.m_msw) * bits_in_word -
942 scfx_find_msb(frac_part.m_mant[frac_part.m_msw]) - 1;
943 frac_zeros = (int)std::floor(frac_wl * std::log10(2.));
944
945 scfx_rep temp;
946 sc_dt::multiply(temp, frac_part, pow10_fx(frac_zeros));
947 frac_part = temp;
948 if (frac_part.m_msw == frac_part.size() - 1)
949 frac_part.resize_to(frac_part.size() + 1, 1);
950
951 frac_digits = frac_zeros;
952 if (!zero_digits) {
953 for (i = 0; i < frac_zeros; i++)
954 s += '0';
955 frac_zeros = 0;
956 }
957
958 while (!frac_part.is_zero()) {
959 frac_part.multiply_by_ten();
960 int n = frac_part.m_mant[frac_part.m_msw + 1];
961
962 if (zero_digits) {
963 if (n == 0)
964 frac_zeros++;
965 else
966 zero_digits = false;
967 }
968
969 if (! zero_digits)
970 s += static_cast<char>('0' + n);
971
972 frac_part.m_mant[frac_part.m_msw + 1] = 0;
973 frac_digits++;
974 }
975 }
976
977 // print exponent
978 if (fmt != SC_F) {
979 if (frac_digits == 0)
980 scfx_print_exp(s, int_zeros);
981 else if (int_digits == 0)
982 scfx_print_exp(s, -frac_zeros);
983 }
984}
985
986void
987print_other(scfx_string &s, const scfx_rep &a, sc_numrep numrep, int w_prefix,
988 sc_fmt fmt, const scfx_params *params)
989{
990 scfx_rep b = a;
991
992 sc_numrep numrep2 = numrep;
993
994 bool numrep_is_sm = (numrep == SC_BIN_SM ||
995 numrep == SC_OCT_SM ||
996 numrep == SC_HEX_SM);
997
998 if (numrep_is_sm) {
999 if (b.is_neg()) {
1000 s += '-';
1001 b = *neg_scfx_rep(a);
1002 }
1003 switch (numrep) {
1004 case SC_BIN_SM:
1005 numrep2 = SC_BIN_US;
1006 break;
1007 case SC_OCT_SM:
1008 numrep2 = SC_OCT_US;
1009 break;
1010 case SC_HEX_SM:
1011 numrep2 = SC_HEX_US;
1012 break;
1013 default:
1014 ;
1015 }
1016 }
1017
1018 if (w_prefix != 0) {
1019 scfx_print_prefix(s, numrep);
1020 }
1021
1022 numrep = numrep2;
1023
1024 int msb, lsb;
1025
1026 if (params != 0) {
1027 msb = params->iwl() - 1;
1028 lsb = params->iwl() - params->wl();
1029
1030 if (params->enc() == SC_TC_ &&
1031 (numrep == SC_BIN_US ||
1032 numrep == SC_OCT_US ||
1033 numrep == SC_HEX_US) &&
1034 !numrep_is_sm &&
1035 params->wl() > 1) {
1036 --msb;
1037 } else if (params->enc() == SC_US_ &&
1038 (numrep == SC_BIN ||
1039 numrep == SC_OCT ||
1040 numrep == SC_HEX ||
1041 numrep == SC_CSD)) {
1042 ++msb;
1043 }
1044 } else {
1045 if (b.is_zero()) {
1046 msb = 0;
1047 lsb = 0;
1048 } else {
1049 msb = (b.m_msw - b.m_wp) * bits_in_word
1050 + scfx_find_msb(b.m_mant[ b.m_msw ]) + 1;
1051 while (b.get_bit(msb) == b.get_bit(msb - 1))
1052 --msb;
1053
1054 if (numrep == SC_BIN_US ||
1055 numrep == SC_OCT_US ||
1056 numrep == SC_HEX_US) {
1057 --msb;
1058 }
1059
1060 lsb = (b.m_lsw - b.m_wp) * bits_in_word +
1061 scfx_find_lsb(b.m_mant[b.m_lsw]);
1062
1063 }
1064 }
1065
1066 int step;
1067
1068 switch (numrep) {
1069 case SC_BIN:
1070 case SC_BIN_US:
1071 case SC_CSD:
1072 step = 1;
1073 break;
1074 case SC_OCT:
1075 case SC_OCT_US:
1076 step = 3;
1077 break;
1078 case SC_HEX:
1079 case SC_HEX_US:
1080 step = 4;
1081 break;
1082 default:
1083 SC_REPORT_FATAL(sc_core::SC_ID_ASSERTION_FAILED_,
1084 "unexpected sc_numrep");
1085 sc_core::sc_abort();
1086 }
1087
1088 msb = (int)std::ceil(double(msb + 1) / step) * step - 1;
1089
1090 lsb = (int)std::floor(double(lsb) / step) * step;
1091
1092 if (msb < 0) {
1093 s += '.';
1094 if (fmt == SC_F) {
1095 int sign = (b.is_neg()) ? (1 << step) - 1 : 0;
1096 for (int i = (msb + 1) / step; i < 0; i++) {
1097 if (sign < 10)
1098 s += static_cast<char>(sign + '0');
1099 else
1100 s += static_cast<char>(sign + 'a' - 10);
1101 }
1102 }
1103 }
1104
1105 int i = msb;
1106 while (i >= lsb) {
1107 int value = 0;
1108 for (int j = step - 1; j >= 0; --j) {
1109 value += static_cast<int>(b.get_bit(i)) << j;
1110 --i;
1111 }
1112 if (value < 10)
1113 s += static_cast<char>(value + '0');
1114 else
1115 s += static_cast<char>(value + 'a' - 10);
1116 if (i == -1)
1117 s += '.';
1118 }
1119
1120 if (lsb > 0 && fmt == SC_F) {
1121 for (int i = lsb / step; i > 0; i--)
1122 s += '0';
1123 }
1124
1125 if (s[s.length() - 1] == '.')
1126 s.discard(1);
1127
1128 if (fmt != SC_F) {
1129 if (msb < 0)
1130 scfx_print_exp(s, (msb + 1) / step);
1131 else if (lsb > 0)
1132 scfx_print_exp(s, lsb / step);
1133 }
1134
1135 if (numrep == SC_CSD)
1136 scfx_tc2csd(s, w_prefix);
1137}
1138
1139const char *
1140scfx_rep::to_string(sc_numrep numrep, int w_prefix,
1141 sc_fmt fmt, const scfx_params *params) const
1142{
1143 static scfx_string s;
1144
1145 s.clear();
1146
1147 if (is_nan()) {
1148 scfx_print_nan(s);
1149 } else if (is_inf()) {
1150 scfx_print_inf(s, is_neg());
1151 } else if (is_neg() && !is_zero() &&
1152 (numrep == SC_BIN_US ||
1153 numrep == SC_OCT_US ||
1154 numrep == SC_HEX_US)) {
1155 s += "negative";
1156 } else if (numrep == SC_DEC || numrep == SC_NOBASE) {
1157 sc_dt::print_dec(s, *this, w_prefix, fmt);
1158 } else {
1159 sc_dt::print_other(s, *this, numrep, w_prefix, fmt, params);
1160 }
1161
1162 return s;
1163}
1164
1165
1166// ----------------------------------------------------------------------------
1167// ADD
1168//
1169// add two mantissas of the same size
1170// result has the same size
1171// returns carry of operation
1172// ----------------------------------------------------------------------------
1173
1174static inline int
1175add_mants(int size, scfx_mant &result, const scfx_mant &a, const scfx_mant &b)
1176{
1177 unsigned int carry = 0;
1178
1179 int index = 0;
1180
1181 do {
1182 word x = a[index];
1183 word y = b[index];
1184
1185 y += carry;
1186 carry = y < carry;
1187 y += x;
1188 carry += y < x;
1189 result[index] = y;
1190 } while (++index < size);
1191
1192 return (carry ? 1 : 0);
1193}
1194
1195static inline int
1196sub_mants(int size, scfx_mant &result, const scfx_mant &a, const scfx_mant &b)
1197{
1198 unsigned carry = 0;
1199
1200 int index = 0;
1201
1202 do {
1203 word x = a[index];
1204 word y = b[index];
1205
1206 y += carry;
1207 carry = y < carry;
1208 y = x - y;
1209 carry += y > x;
1210 result[index] = y;
1211 } while (++index < size);
1212
1213 return (carry ? 1 : 0);
1214}
1215
1216scfx_rep *
1217add_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int max_wl)
1218{
1219 scfx_rep &result = *new scfx_rep;
1220
1221 //
1222 // check for special cases
1223 //
1224 if (lhs.is_nan() || rhs.is_nan() ||
1225 (lhs.is_inf() && rhs.is_inf() && lhs.m_sign != rhs.m_sign)) {
1226 result.set_nan();
1227 return &result;
1228 }
1229
1230 if (lhs.is_inf()) {
1231 result.set_inf(lhs.m_sign);
1232 return &result;
1233 }
1234
1235 if (rhs.is_inf()) {
1236 result.set_inf(rhs.m_sign);
1237 return &result;
1238 }
1239
1240 //
1241 // align operands if needed
1242 //
1243 scfx_mant_ref lhs_mant;
1244 scfx_mant_ref rhs_mant;
1245
1246 int len_mant = lhs.size();
1247 int new_wp = lhs.m_wp;
1248
1249 align(lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant);
1250
1251 //
1252 // size the result mantissa
1253 //
1254 result.resize_to(len_mant);
1255 result.m_wp = new_wp;
1256
1257 //
1258 // do it
1259 //
1260 if (lhs.m_sign == rhs.m_sign) {
1261 add_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
1262 result.m_sign = lhs.m_sign;
1263 } else {
1264 int cmp = compare_abs(lhs, rhs);
1265
1266 if (cmp == 1) {
1267 sub_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
1268 result.m_sign = lhs.m_sign;
1269 } else if (cmp == -1) {
1270 sub_mants(len_mant, result.m_mant, rhs_mant, lhs_mant);
1271 result.m_sign = rhs.m_sign;
1272 } else {
1273 result.m_mant.clear();
1274 result.m_sign = 1;
1275 }
1276 }
1277
1278 result.find_sw();
1279 result.round(max_wl);
1280
1281 return &result;
1282}
1283
1284
1285// ----------------------------------------------------------------------------
1286// SUB
1287//
1288// sub two word's of the same size
1289// result has the same size
1290// returns carry of operation
1291// ----------------------------------------------------------------------------
1292
1293static inline int
1294sub_with_index(scfx_mant &a, int a_msw, int /*a_lsw*/,
1295 const scfx_mant &b, int b_msw, int b_lsw)
1296{
1297 unsigned carry = 0;
1298
1299 int size = b_msw - b_lsw;
1300 int a_index = a_msw - size;
1301 int b_index = b_msw - size;
1302
1303 do {
1304 word x = a[a_index];
1305 word y = b[b_index];
1306
1307 y += carry;
1308 carry = y < carry;
1309 y = x - y;
1310 carry += y > x;
1311 a[a_index] = y;
1312
1313 a_index++;
1314 b_index++;
1315 } while (size--);
1316
1317 if (carry) {
1318 // special case: a[a_msw + 1] == 1
1319 a[a_msw + 1] = 0;
1320 }
1321
1322 return (carry ? 1 : 0);
1323}
1324
1325scfx_rep *
1326sub_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int max_wl)
1327{
1328 scfx_rep &result = *new scfx_rep;
1329
1330 //
1331 // check for special cases
1332 //
1333 if (lhs.is_nan() || rhs.is_nan() ||
1334 (lhs.is_inf() && rhs.is_inf() && lhs.m_sign == rhs.m_sign)) {
1335 result.set_nan();
1336 return &result;
1337 }
1338
1339 if (lhs.is_inf()) {
1340 result.set_inf(lhs.m_sign);
1341 return &result;
1342 }
1343
1344 if (rhs.is_inf()) {
1345 result.set_inf(-1 * rhs.m_sign);
1346 return &result;
1347 }
1348
1349 //
1350 // align operands if needed
1351 //
1352 scfx_mant_ref lhs_mant;
1353 scfx_mant_ref rhs_mant;
1354
1355 int len_mant = lhs.size();
1356 int new_wp = lhs.m_wp;
1357
1358 align(lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant);
1359
1360 //
1361 // size the result mantissa
1362 //
1363 result.resize_to(len_mant);
1364 result.m_wp = new_wp;
1365
1366 //
1367 // do it
1368 //
1369 if (lhs.m_sign != rhs.m_sign) {
1370 add_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
1371 result.m_sign = lhs.m_sign;
1372 } else {
1373 int cmp = compare_abs(lhs, rhs);
1374
1375 if (cmp == 1) {
1376 sub_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
1377 result.m_sign = lhs.m_sign;
1378 } else if (cmp == -1) {
1379 sub_mants(len_mant, result.m_mant, rhs_mant, lhs_mant);
1380 result.m_sign = -rhs.m_sign;
1381 } else {
1382 result.m_mant.clear();
1383 result.m_sign = 1;
1384 }
1385 }
1386
1387 result.find_sw();
1388 result.round(max_wl);
1389
1390 return &result;
1391}
1392
1393
1394// ----------------------------------------------------------------------------
1395// MUL
1396// ----------------------------------------------------------------------------
1397
1398union word_short
1399{
1400 word l;
1401 struct
1402 {
1403#if defined(SC_BOOST_BIG_ENDIAN)
1404 half_word u;
1405 half_word l;
1406#elif defined(SC_BOOST_LITTLE_ENDIAN)
1407 half_word l;
1408 half_word u;
1409#endif
1410 } s;
1411};
1412
1413#if defined(SC_BOOST_BIG_ENDIAN)
1414static const int half_word_incr = -1;
1415#elif defined(SC_BOOST_LITTLE_ENDIAN)
1416static const int half_word_incr = 1;
1417#endif
1418
1419void
1420multiply(scfx_rep &result, const scfx_rep &lhs, const scfx_rep &rhs,
1421 int max_wl)
1422{
1423 //
1424 // check for special cases
1425 //
1426 if (lhs.is_nan() || rhs.is_nan() ||
1427 (lhs.is_inf() && rhs.is_zero()) ||
1428 (lhs.is_zero() && rhs.is_inf())) {
1429 result.set_nan();
1430 return;
1431 }
1432
1433 if (lhs.is_inf() || rhs.is_inf()) {
1434 result.set_inf(lhs.m_sign * rhs.m_sign);
1435 return;
1436 }
1437
1438 if (lhs.is_zero() || rhs.is_zero()) {
1439 result.set_zero(lhs.m_sign * rhs.m_sign);
1440 return;
1441 }
1442
1443 //
1444 // do it
1445 //
1446 int len_lhs = lhs.m_msw - lhs.m_lsw + 1;
1447 int len_rhs = rhs.m_msw - rhs.m_lsw + 1;
1448
1449 int new_size = sc_max(min_mant, len_lhs + len_rhs);
1450 int new_wp = (lhs.m_wp - lhs.m_lsw) + (rhs.m_wp - rhs.m_lsw);
1451 int new_sign = lhs.m_sign * rhs.m_sign;
1452
1453 result.resize_to(new_size);
1454 result.m_mant.clear();
1455 result.m_wp = new_wp;
1456 result.m_sign = new_sign;
1457 result.m_state = scfx_rep::normal;
1458
1459 half_word *s1 = lhs.m_mant.half_addr(lhs.m_lsw);
1460 half_word *s2 = rhs.m_mant.half_addr(rhs.m_lsw);
1461
1462 half_word *t = result.m_mant.half_addr();
1463
1464 len_lhs <<= 1;
1465 len_rhs <<= 1;
1466
1467 int i1, i2;
1468
1469 for (i1 = 0; i1 * half_word_incr < len_lhs; i1 += half_word_incr) {
1470 word_short ls;
1471 ls.l = 0;
1472
1473 half_word v1 = s1[i1];
1474
1475 for (i2 = 0; i2 * half_word_incr < len_rhs; i2 += half_word_incr) {
1476 ls.l += v1 * s2[i2];
1477 ls.s.l = ls.s.u + ((t[i2] += ls.s.l) < ls.s.l);
1478 ls.s.u = 0;
1479 }
1480
1481 t[i2] = ls.s.l;
1482 t += half_word_incr;
1483 }
1484
1485 result.find_sw();
1486 result.round(max_wl);
1487}
1488
1489
1490// ----------------------------------------------------------------------------
1491// DIV
1492// ----------------------------------------------------------------------------
1493
1494scfx_rep *
1495div_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int div_wl)
1496{
1497 scfx_rep &result = *new scfx_rep;
1498
1499 //
1500 // check for special cases
1501 //
1502 if (lhs.is_nan() || rhs.is_nan() || (lhs.is_inf() && rhs.is_inf()) ||
1503 (lhs.is_zero() && rhs.is_zero())) {
1504 result.set_nan();
1505 return &result;
1506 }
1507
1508 if (lhs.is_inf() || rhs.is_zero()) {
1509 result.set_inf(lhs.m_sign * rhs.m_sign);
1510 return &result;
1511 }
1512
1513 if (lhs.is_zero() || rhs.is_inf()) {
1514 result.set_zero(lhs.m_sign * rhs.m_sign);
1515 return &result;
1516 }
1517
1518 //
1519 // do it
1520 //
1521
1522 // compute one bit more for rounding
1523 div_wl++;
1524
1525 result.resize_to(sc_max(n_word(div_wl) + 1, min_mant));
1526 result.m_mant.clear();
1527 result.m_sign = lhs.m_sign * rhs.m_sign;
1528
1529 int msb_lhs = scfx_find_msb(lhs.m_mant[lhs.m_msw]) +
1530 (lhs.m_msw - lhs.m_wp) * bits_in_word;
1531 int msb_rhs = scfx_find_msb(rhs.m_mant[rhs.m_msw]) +
1532 (rhs.m_msw - rhs.m_wp) * bits_in_word;
1533
1534 int msb_res = msb_lhs - msb_rhs;
1535 int to_shift = -msb_res % bits_in_word;
1536 int result_index;
1537
1538 int c = (msb_res % bits_in_word >= 0) ? 1 : 0;
1539
1540 result_index = (result.size() - c) * bits_in_word + msb_res % bits_in_word;
1541 result.m_wp = (result.size() - c) - msb_res / bits_in_word;
1542
1543 scfx_rep remainder = lhs;
1544
1545 // align msb from remainder to msb from rhs
1546 remainder.lshift(to_shift);
1547
1548 // make sure msw(remainder) < size - 1
1549 if (remainder.m_msw == remainder.size() - 1)
1550 remainder.resize_to(remainder.size() + 1, 1);
1551
1552 // make sure msw(remainder) >= msw(rhs)!
1553 int msw_diff = rhs.m_msw - remainder.m_msw;
1554 if (msw_diff > 0)
1555 remainder.resize_to(remainder.size() + msw_diff, -1);
1556
1557 int counter;
1558
1559 for (counter = div_wl; counter && !remainder.is_zero(); counter--) {
1560 if (compare_msw_ff(rhs, remainder) <= 0) {
1561 result.set_bin(result_index);
1562 sub_with_index(remainder.m_mant, remainder.m_msw, remainder.m_lsw,
1563 rhs.m_mant, rhs.m_msw, rhs.m_lsw);
1564 }
1565 result_index--;
1566 remainder.shift_left(1);
1567 remainder.m_lsw = remainder.find_lsw();
1568 }
1569
1570 // perform convergent rounding, if needed
1571 if (counter == 0) {
1572 int index = result_index + 1 - result.m_wp * bits_in_word;
1573
1574 scfx_index x = result.calc_indices(index);
1575 scfx_index x1 = result.calc_indices(index + 1);
1576
1577 if (result.o_bit_at(x) && result.o_bit_at(x1))
1578 result.q_incr(x);
1579
1580 result.m_r_flag = true;
1581 }
1582
1583 result.find_sw();
1584
1585 return &result;
1586}
1587
1588// ----------------------------------------------------------------------------
1589// destructive shift mantissa to the left
1590// ----------------------------------------------------------------------------
1591
1592void
1593scfx_rep::lshift(int n)
1594{
1595 if (n == 0)
1596 return;
1597
1598 if (n < 0) {
1599 rshift(-n);
1600 return;
1601 }
1602
1603 if (is_normal()) {
1604 int shift_bits = n % bits_in_word;
1605 int shift_words = n / bits_in_word;
1606
1607 // resize if needed
1608 if (m_msw == size() - 1 &&
1609 scfx_find_msb(m_mant[m_msw]) >= bits_in_word - shift_bits)
1610 resize_to(size() + 1, 1);
1611
1612 // do it
1613 m_wp -= shift_words;
1614 shift_left(shift_bits);
1615 find_sw();
1616 }
1617}
1618
1619// ----------------------------------------------------------------------------
1620// destructive shift mantissa to the right
1621// ----------------------------------------------------------------------------
1622
1623void
1624scfx_rep::rshift(int n)
1625{
1626 if (n == 0)
1627 return;
1628
1629 if (n < 0) {
1630 lshift(-n);
1631 return;
1632 }
1633
1634 if (is_normal()) {
1635 int shift_bits = n % bits_in_word;
1636 int shift_words = n / bits_in_word;
1637
1638 // resize if needed
1639 if (m_lsw == 0 && scfx_find_lsb(m_mant[m_lsw]) < shift_bits)
1640 resize_to(size() + 1, -1);
1641
1642 // do it
1643 m_wp += shift_words;
1644 shift_right(shift_bits);
1645 find_sw();
1646 }
1647}
1648
1649
1650// ----------------------------------------------------------------------------
1651// FRIEND FUNCTION : compare_abs
1652//
1653// Compares the absolute values of two scfx_reps, excluding the special cases.
1654// ----------------------------------------------------------------------------
1655
1656int
1657compare_abs(const scfx_rep &a, const scfx_rep &b)
1658{
1659 // check for zero
1660 word a_word = a.m_mant[a.m_msw];
1661 word b_word = b.m_mant[b.m_msw];
1662
1663 if (a_word == 0 || b_word == 0) {
1664 if (a_word != 0)
1665 return 1;
1666 if (b_word != 0)
1667 return -1;
1668 return 0;
1669 }
1670
1671 // compare msw index
1672 int a_msw = a.m_msw - a.m_wp;
1673 int b_msw = b.m_msw - b.m_wp;
1674
1675 if (a_msw > b_msw)
1676 return 1;
1677
1678 if (a_msw < b_msw)
1679 return -1;
1680
1681 // compare content
1682 int a_i = a.m_msw;
1683 int b_i = b.m_msw;
1684
1685 while (a_i >= a.m_lsw && b_i >= b.m_lsw) {
1686 a_word = a.m_mant[a_i];
1687 b_word = b.m_mant[b_i];
1688 if (a_word > b_word)
1689 return 1;
1690 if (a_word < b_word)
1691 return -1;
1692 --a_i;
1693 --b_i;
1694 }
1695
1696 bool a_zero = true;
1697 while (a_i >= a.m_lsw) {
1698 a_zero = a_zero && (a.m_mant[a_i] == 0);
1699 --a_i;
1700 }
1701
1702 bool b_zero = true;
1703 while (b_i >= b.m_lsw) {
1704 b_zero = b_zero && (b.m_mant[b_i] == 0);
1705 --b_i;
1706 }
1707
1708 // assertion: a_zero || b_zero
1709
1710 if (!a_zero && b_zero)
1711 return 1;
1712
1713 if (a_zero && !b_zero)
1714 return -1;
1715
1716 return 0;
1717}
1718
1719// ----------------------------------------------------------------------------
1720// FRIEND FUNCTION : cmp_scfx_rep
1721//
1722// Compares the values of two scfx_reps, including the special cases.
1723// ----------------------------------------------------------------------------
1724
1725int
1726cmp_scfx_rep(const scfx_rep &a, const scfx_rep &b)
1727{
1728 // handle special cases
1729
1730 if (a.is_nan() || b.is_nan()) {
1731 return 2;
1732 }
1733
1734 if (a.is_inf() || b.is_inf()) {
1735 if (a.is_inf()) {
1736 if (!a.is_neg()) {
1737 if (b.is_inf() && !b.is_neg()) {
1738 return 0;
1739 } else {
1740 return 1;
1741 }
1742 } else {
1743 if (b.is_inf() && b.is_neg()) {
1744 return 0;
1745 } else {
1746 return -1;
1747 }
1748 }
1749 }
1750 if (b.is_inf()) {
1751 if (!b.is_neg()) {
1752 return -1;
1753 } else {
1754 return 1;
1755 }
1756 }
1757 }
1758
1759 if (a.is_zero() && b.is_zero()) {
1760 return 0;
1761 }
1762
1763 // compare sign
1764 if (a.m_sign != b.m_sign) {
1765 return a.m_sign;
1766 }
1767
1768 return (a.m_sign * compare_abs(a, b));
1769}
1770
1771
1772// ----------------------------------------------------------------------------
1773// PRIVATE METHOD : quantization
1774//
1775// Performs destructive quantization.
1776// ----------------------------------------------------------------------------
1777
1778void
1779scfx_rep::quantization(const scfx_params &params, bool &q_flag)
1780{
1781 scfx_index x = calc_indices(params.iwl() - params.wl());
1782
1783 if (x.wi() < 0)
1784 return;
1785
1786 if (x.wi() >= size())
1787 resize_to(x.wi() + 1, 1);
1788
1789 bool qb = q_bit(x);
1790 bool qz = q_zero(x);
1791
1792 q_flag = (qb || ! qz);
1793
1794 if (q_flag) {
1795 switch (params.q_mode()) {
1796 case SC_TRN: // truncation
1797 {
1798 if (is_neg())
1799 q_incr(x);
1800 break;
1801 }
1802 case SC_RND: // rounding to plus infinity
1803 {
1804 if (!is_neg()) {
1805 if (qb)
1806 q_incr(x);
1807 } else {
1808 if (qb && !qz)
1809 q_incr(x);
1810 }
1811 break;
1812 }
1813 case SC_TRN_ZERO: // truncation to zero
1814 {
1815 break;
1816 }
1817 case SC_RND_INF: // rounding to infinity
1818 {
1819 if (qb)
1820 q_incr(x);
1821 break;
1822 }
1823 case SC_RND_CONV: // convergent rounding
1824 {
1825 if ((qb && !qz) || (qb && qz && q_odd(x)))
1826 q_incr(x);
1827 break;
1828 }
1829 case SC_RND_ZERO: // rounding to zero
1830 {
1831 if (qb && !qz)
1832 q_incr(x);
1833 break;
1834 }
1835 case SC_RND_MIN_INF: // rounding to minus infinity
1836 {
1837 if (!is_neg()) {
1838 if (qb && !qz)
1839 q_incr(x);
1840 } else {
1841 if (qb)
1842 q_incr(x);
1843 }
1844 break;
1845 }
1846 default:
1847 ;
1848 }
1849 q_clear(x);
1850
1851 find_sw();
1852 }
1853}
1854
1855
1856// ----------------------------------------------------------------------------
1857// PRIVATE METHOD : overflow
1858//
1859// Performs destructive overflow handling.
1860// ----------------------------------------------------------------------------
1861
1862void
1863scfx_rep::overflow(const scfx_params &params, bool &o_flag)
1864{
1865 scfx_index x = calc_indices(params.iwl() - 1);
1866
1867 if (x.wi() >= size())
1868 resize_to(x.wi() + 1, 1);
1869
1870 if (x.wi() < 0) {
1871 resize_to(size() - x.wi(), -1);
1872 x.wi(0);
1873 }
1874
1875 bool zero_left = o_zero_left(x);
1876 bool bit_at = o_bit_at(x);
1877 bool zero_right = o_zero_right(x);
1878
1879 bool under = false;
1880 bool over = false;
1881
1882 sc_enc enc = params.enc();
1883
1884 if (enc == SC_TC_) {
1885 if (is_neg()) {
1886 if (params.o_mode() == SC_SAT_SYM)
1887 under = (!zero_left || bit_at);
1888 else
1889 under = (!zero_left || (zero_left && bit_at && ! zero_right));
1890 } else {
1891 over = (! zero_left || bit_at);
1892 }
1893 } else {
1894 if (is_neg())
1895 under = (!is_zero());
1896 else
1897 over = (!zero_left);
1898 }
1899
1900 o_flag = (under || over);
1901
1902 if (o_flag) {
1903 scfx_index x2 = calc_indices(params.iwl() - params.wl());
1904
1905 if (x2.wi() < 0) {
1906 resize_to(size() - x2.wi(), -1);
1907 x.wi(x.wi() - x2.wi());
1908 x2.wi(0);
1909 }
1910
1911 switch (params.o_mode()) {
1912 case SC_WRAP: // wrap-around
1913 {
1914 int n_bits = params.n_bits();
1915
1916 if (n_bits == 0) {
1917 // wrap-around all 'wl' bits
1918 toggle_tc();
1919 o_extend(x, enc);
1920 toggle_tc();
1921 } else if (n_bits < params.wl()) {
1922 scfx_index x3 = calc_indices(params.iwl() - 1 - n_bits);
1923
1924 // wrap-around least significant 'wl - n_bits' bits;
1925 // saturate most significant 'n_bits' bits
1926 toggle_tc();
1927 o_set(x, x3, enc, under);
1928 o_extend(x, enc);
1929 toggle_tc();
1930 } else {
1931 // saturate all 'wl' bits
1932 if (under)
1933 o_set_low(x, enc);
1934 else
1935 o_set_high(x, x2, enc);
1936 }
1937 break;
1938 }
1939 case SC_SAT: // saturation
1940 {
1941 if (under)
1942 o_set_low(x, enc);
1943 else
1944 o_set_high(x, x2, enc);
1945 break;
1946 }
1947 case SC_SAT_SYM: // symmetrical saturation
1948 {
1949 if (under) {
1950 if (enc == SC_TC_)
1951 o_set_high(x, x2, SC_TC_, -1);
1952 else
1953 o_set_low(x, SC_US_);
1954 } else {
1955 o_set_high(x, x2, enc);
1956 }
1957 break;
1958 }
1959 case SC_SAT_ZERO: // saturation to zero
1960 {
1961 set_zero();
1962 break;
1963 }
1964 case SC_WRAP_SM: // sign magnitude wrap-around
1965 {
1966 SC_ERROR_IF_(enc == SC_US_,
1966 "SC_WRAP_SM not defined for unsigned numbers");
1967 sc_core::SC_ID_WRAP_SM_NOT_DEFINED_);
1967
1968 int n_bits = params.n_bits();
1969
1970 if (n_bits == 0) {
1971 scfx_index x4 = calc_indices(params.iwl());
1972
1973 if (x4.wi() >= size())
1974 resize_to(x4.wi() + 1, 1);
1975
1976 toggle_tc();
1977 if (o_bit_at(x4) != o_bit_at(x))
1978 o_invert(x2);
1979 o_extend(x, SC_TC_);
1980 toggle_tc();
1981 } else if (n_bits == 1) {
1982 toggle_tc();
1983 if (is_neg() != o_bit_at(x))
1984 o_invert(x2);
1985 o_extend(x, SC_TC_);
1986 toggle_tc();
1987 } else if (n_bits < params.wl()) {
1988 scfx_index x3 = calc_indices(params.iwl() - 1 - n_bits);
1989 scfx_index x4 = calc_indices(params.iwl() - n_bits);
1990
1991 // wrap-around least significant 'wl - n_bits' bits;
1992 // saturate most significant 'n_bits' bits
1993 toggle_tc();
1994 if (is_neg() == o_bit_at(x4))
1995 o_invert(x2);
1996 o_set(x, x3, SC_TC_, under);
1997 o_extend(x, SC_TC_);
1998 toggle_tc();
1999 } else {
2000 if (under)
2001 o_set_low(x, SC_TC_);
2002 else
2003 o_set_high(x, x2, SC_TC_);
2004 }
2005 break;
2006 }
2007 default:
2008 ;
2009 }
2010
2011 find_sw();
2012 }
2013}
2014
2015
2016// ----------------------------------------------------------------------------
2017// PUBLIC METHOD : cast
2018//
2019// Performs a destructive cast operation on a scfx_rep.
2020// ----------------------------------------------------------------------------
2021
2022void
2023scfx_rep::cast(const scfx_params &params, bool &q_flag, bool &o_flag)
2024{
2025 q_flag = false;
2026 o_flag = false;
2027
2028 // check for special cases
2029 if (is_zero()) {
2030 if (is_neg())
2031 m_sign = 1;
2032 return;
2033 }
2034
2035 // perform casting
2036 quantization(params, q_flag);
2037 overflow(params, o_flag);
2038
2039 // check for special case: -0
2040 if (is_zero() && is_neg())
2041 m_sign = 1;
2042}
2043
2044
2045// ----------------------------------------------------------------------------
2046// make sure, the two mantissas are aligned
2047// ----------------------------------------------------------------------------
2048
2049void
2050align(const scfx_rep &lhs, const scfx_rep &rhs, int &new_wp,
2051 int &len_mant, scfx_mant_ref &lhs_mant, scfx_mant_ref &rhs_mant)
2052{
2053 bool need_lhs = true;
2054 bool need_rhs = true;
2055
2056 if (lhs.m_wp != rhs.m_wp || lhs.size() != rhs.size()) {
2057 int lower_bound_lhs = lhs.m_lsw - lhs.m_wp;
2058 int upper_bound_lhs = lhs.m_msw - lhs.m_wp;
2059 int lower_bound_rhs = rhs.m_lsw - rhs.m_wp;
2060 int upper_bound_rhs = rhs.m_msw - rhs.m_wp;
2061
2062 int lower_bound = sc_min(lower_bound_lhs, lower_bound_rhs);
2063 int upper_bound = sc_max(upper_bound_lhs, upper_bound_rhs);
2064
2065 new_wp = -lower_bound;
2066 len_mant = sc_max(min_mant, upper_bound - lower_bound + 1);
2067
2068 if (new_wp != lhs.m_wp || len_mant != lhs.size()) {
2069 lhs_mant = lhs.resize(len_mant, new_wp);
2070 need_lhs = false;
2071 }
2072
2073 if (new_wp != rhs.m_wp || len_mant != rhs.size()) {
2074 rhs_mant = rhs.resize(len_mant, new_wp);
2075 need_rhs = false;
2076 }
2077 }
2078
2079 if (need_lhs) {
2080 lhs_mant = lhs.m_mant;
2081 }
2082
2083 if (need_rhs) {
2084 rhs_mant = rhs.m_mant;
2085 }
2086}
2087
2088
2089// ----------------------------------------------------------------------------
2090// compare two mantissas
2091// ----------------------------------------------------------------------------
2092
2093int
2094compare_msw_ff(const scfx_rep &lhs, const scfx_rep &rhs)
2095{
2096 // special case: rhs.m_mant[rhs.m_msw + 1] == 1
2097 if (rhs.m_msw < rhs.size() - 1 && rhs.m_mant[rhs.m_msw + 1 ] != 0) {
2098 return -1;
2099 }
2100
2101 int lhs_size = lhs.m_msw - lhs.m_lsw + 1;
2102 int rhs_size = rhs.m_msw - rhs.m_lsw + 1;
2103
2104 int size = sc_min(lhs_size, rhs_size);
2105
2106 int lhs_index = lhs.m_msw;
2107 int rhs_index = rhs.m_msw;
2108
2109 int i;
2110
2111 for (i = 0;
2112 i < size && lhs.m_mant[lhs_index] == rhs.m_mant[rhs_index];
2113 i++) {
2114 lhs_index--;
2115 rhs_index--;
2116 }
2117
2118 if (i == size) {
2119 if (lhs_size == rhs_size) {
2120 return 0;
2121 }
2122
2123 if (lhs_size < rhs_size) {
2124 return -1;
2125 } else {
2126 return 1;
2127 }
2128 }
2129
2130 if (lhs.m_mant[lhs_index] < rhs.m_mant[rhs_index]) {
2131 return -1;
2132 } else {
2133 return 1;
2134 }
2135}
2136
2137
2138// ----------------------------------------------------------------------------
2139// divide the mantissa by ten
2140// ----------------------------------------------------------------------------
2141
2142unsigned int
2143scfx_rep::divide_by_ten()
2144{
2145#if defined(SC_BOOST_BIG_ENDIAN)
2146 half_word *hw = (half_word *)&m_mant[m_msw];
2147#elif defined(SC_BOOST_LITTLE_ENDIAN)
2148 half_word *hw = ((half_word *)&m_mant[m_msw]) + 1;
2149#endif
2150
2151 unsigned int remainder = 0;
2152
2153 word_short ls;
2154 ls.l = 0;
2155
2156#if defined(SC_BOOST_BIG_ENDIAN)
2157 for (int i = 0, end = (m_msw - m_wp + 1) * 2; i < end; i++) {
2158#elif defined(SC_BOOST_LITTLE_ENDIAN)
2159 for (int i = 0, end = -(m_msw - m_wp + 1) * 2; i > end; i--) {
2160#endif
2161 ls.s.u = static_cast<half_word>(remainder);
2162 ls.s.l = hw[i];
2163 remainder = ls.l % 10;
2164 ls.l /= 10;
2165 hw[i] = ls.s.l;
2166 }
2167
2168 return remainder;
2169}
2170
2171
2172// ----------------------------------------------------------------------------
2173// multiply the mantissa by ten
2174// ----------------------------------------------------------------------------
2175
2176void
2177scfx_rep::multiply_by_ten()
2178{
2179 int size = m_mant.size() + 1;
2180
2181 scfx_mant mant8(size);
2182 scfx_mant mant2(size);
2183
2184 size--;
2185
2186 mant8[size] = (m_mant[size - 1] >> (bits_in_word - 3));
2187 mant2[size] = (m_mant[size - 1] >> (bits_in_word - 1));
2188
2189 while (--size) {
2190 mant8[size] = (m_mant[size] << 3) |
2191 (m_mant[size - 1] >> (bits_in_word - 3));
2192 mant2[size] = (m_mant[size] << 1) |
2193 (m_mant[size - 1] >> (bits_in_word - 1));
2194 }
2195
2196 mant8[0] = (m_mant[0] << 3);
2197 mant2[0] = (m_mant[0] << 1);
2198
2199 add_mants(m_mant.size(), m_mant, mant8, mant2);
2200}
2201
2202
2203// ----------------------------------------------------------------------------
2204// normalize
2205// ----------------------------------------------------------------------------
2206
2207void
2208scfx_rep::normalize(int exponent)
2209{
2210 int shift = exponent % bits_in_word;
2211 if (shift < 0) {
2212 shift += bits_in_word;
2213 }
2214
2215 if (shift) {
2216 shift_left(shift);
2217 }
2218
2219 find_sw();
2220
2221 m_wp = (shift - exponent) / bits_in_word;
2222}
2223
2224
2225// ----------------------------------------------------------------------------
2226// return a new mantissa that is aligned and resized
2227// ----------------------------------------------------------------------------
2228
2229scfx_mant *
2230scfx_rep::resize(int new_size, int new_wp) const
2231{
2232 scfx_mant *result = new scfx_mant(new_size);
2233
2234 result->clear();
2235
2236 int shift = new_wp - m_wp;
2237
2238 for (int j = m_lsw; j <= m_msw; j++) {
2239 (*result)[j + shift] = m_mant[j];
2240 }
2241
2242 return result;
2243}
2244
2245
2246// ----------------------------------------------------------------------------
2247// set a single bit
2248// ----------------------------------------------------------------------------
2249
2250void
2251scfx_rep::set_bin(int i)
2252{
2253 m_mant[i >> 5] |= 1 << (i & 31);
2254}
2255
2256
2257// ----------------------------------------------------------------------------
2258// set three bits
2259// ----------------------------------------------------------------------------
2260
2261void
2262scfx_rep::set_oct(int i, int n)
2263{
2264 if (n & 1) {
2265 m_mant[i >> 5] |= 1 << (i & 31);
2266 }
2267 i++;
2268 if (n & 2) {
2269 m_mant[i >> 5] |= 1 << (i & 31);
2270 }
2271 i++;
2272 if (n & 4) {
2273 m_mant[i >> 5] |= 1 << (i & 31);
2274 }
2275}
2276
2277
2278// ----------------------------------------------------------------------------
2279// set four bits
2280// ----------------------------------------------------------------------------
2281
2282void
2283scfx_rep::set_hex(int i, int n)
2284{
2285 if (n & 1) {
2286 m_mant[i >> 5] |= 1 << (i & 31);
2287 }
2288 i++;
2289 if (n & 2) {
2290 m_mant[i >> 5] |= 1 << (i & 31);
2291 }
2292 i++;
2293 if (n & 4) {
2294 m_mant[i >> 5] |= 1 << (i & 31);
2295 }
2296 i++;
2297 if (n & 8) {
2298 m_mant[i >> 5] |= 1 << (i & 31);
2299 }
2300}
2301
2302
2303// ----------------------------------------------------------------------------
2304// PRIVATE METHOD : shift_left
2305//
2306// Shifts a scfx_rep to the left by a MAXIMUM of bits_in_word - 1 bits.
2307// ----------------------------------------------------------------------------
2308
2309void
2310scfx_rep::shift_left(int n)
2311{
2312 if (n != 0) {
2313 int shift_left = n;
2314 int shift_right = bits_in_word - n;
2315
2316 SC_ASSERT_(!(m_mant[size() - 1] >> shift_right),
2317 "shift_left overflow");
2318
2319 for (int i = size() - 1; i > 0; i--) {
2320 m_mant[i] = (m_mant[i] << shift_left) |
2321 (m_mant[i - 1] >> shift_right);
2322 }
2323 m_mant[0] <<= shift_left;
2324 }
2325}
2326
2327
2328// ----------------------------------------------------------------------------
2329// PRIVATE METHOD : shift_right
2330//
2331// Shifts a scfx_rep to the right by a MAXIMUM of bits_in_word - 1 bits.
2332// ----------------------------------------------------------------------------
2333
2334void
2335scfx_rep::shift_right(int n)
2336{
2337 if (n != 0) {
2338 int shift_left = bits_in_word - n;
2339 int shift_right = n;
2340
2341 SC_ASSERT_(!(m_mant[0] << shift_left), "shift_right overflow");
2342
2343 for (int i = 0; i < size() - 1; i++) {
2344 m_mant[i] = (m_mant[i] >> shift_right) |
2345 (m_mant[i + 1] << shift_left);
2346 }
2347 m_mant[size() - 1] >>= shift_right;
2348 }
2349}
2350
2351
2352// ----------------------------------------------------------------------------
2353// METHOD : get_bit
2354//
2355// Tests a bit, in two's complement.
2356// ----------------------------------------------------------------------------
2357
2358bool
2359scfx_rep::get_bit(int i) const
2360{
2361 if (!is_normal())
2362 return false;
2363
2364 scfx_index x = calc_indices(i);
2365
2366 if (x.wi() >= size())
2367 return is_neg();
2368
2369 if (x.wi() < 0)
2370 return false;
2371
2372 const_cast<scfx_rep*>(this)->toggle_tc();
2373
2374 bool result = (m_mant[x.wi()] & (1 << x.bi())) != 0;
2375
2376 const_cast<scfx_rep *>(this)->toggle_tc();
2377
2378 return result;
2379}
2380
2381
2382// ----------------------------------------------------------------------------
2383// METHOD : set
2384//
2385// Sets a bit, in two's complement, between iwl-1 and -fwl.
2386// ----------------------------------------------------------------------------
2387
2388bool
2389scfx_rep::set(int i, const scfx_params &params)
2390{
2391 if (!is_normal())
2392 return false;
2393
2394 scfx_index x = calc_indices(i);
2395
2396 if (x.wi() >= size()) {
2397 if (is_neg())
2398 return true;
2399 else
2400 resize_to(x.wi() + 1, 1);
2401 } else if (x.wi() < 0) {
2402 resize_to(size() - x.wi(), -1);
2403 x.wi(0);
2404 }
2405
2406 toggle_tc();
2407
2408 m_mant[x.wi()] |= 1 << x.bi();
2409
2410 if (i == params.iwl() - 1)
2411 o_extend(x, params.enc()); // sign extension
2412
2413 toggle_tc();
2414
2415 find_sw();
2416
2417 return true;
2418}
2419
2420
2421// ----------------------------------------------------------------------------
2422// METHOD : clear
2423//
2424// Clears a bit, in two's complement, between iwl-1 and -fwl.
2425// ----------------------------------------------------------------------------
2426
2427bool
2428scfx_rep::clear(int i, const scfx_params &params)
2429{
2430 if (!is_normal())
2431 return false;
2432
2433 scfx_index x = calc_indices(i);
2434
2435 if (x.wi() >= size()) {
2436 if (!is_neg())
2437 return true;
2438 else
2439 resize_to(x.wi() + 1, 1);
2440 } else if (x.wi() < 0) {
2441 return true;
2442 }
2443
2444 toggle_tc();
2445
2446 m_mant[x.wi()] &= ~(1 << x.bi());
2447
2448 if (i == params.iwl() - 1)
2449 o_extend(x, params.enc()); // sign extension
2450
2451 toggle_tc();
2452
2453 find_sw();
2454
2455 return true;
2456}
2457
2458
2459// ----------------------------------------------------------------------------
2460// METHOD : get_slice
2461// ----------------------------------------------------------------------------
2462
2463bool
2464scfx_rep::get_slice(int i, int j, const scfx_params &, sc_bv_base &bv) const
2465{
2466 if (is_nan() || is_inf())
2467 return false;
2468
2469 // get the bits
2470
2471 int l = j;
2472 for (int k = 0; k < bv.length(); ++k) {
2473 bv[k] = get_bit(l);
2474
2475 if (i >= j)
2476 ++l;
2477 else
2478 --l;
2479 }
2480
2481 return true;
2482}
2483
2484bool
2485scfx_rep::set_slice(int i, int j, const scfx_params &params,
2486 const sc_bv_base &bv)
2487{
2488 if (is_nan() || is_inf())
2489 return false;
2490
2491 // set the bits
2492 int l = j;
2493 for (int k = 0; k < bv.length(); ++k) {
2494 if (bv[k].to_bool())
2495 set(l, params);
2496 else
2497 clear(l, params);
2498
2499 if (i >= j)
2500 ++l;
2501 else
2502 --l;
2503 }
2504
2505 return true;
2506}
2507
2508
2509// ----------------------------------------------------------------------------
2510// METHOD : print
2511// ----------------------------------------------------------------------------
2512
2513void
2514scfx_rep::print(::std::ostream &os) const
2515{
2516 os << to_string(SC_DEC, -1, SC_E);
2517}
2518
2519
2520// ----------------------------------------------------------------------------
2521// METHOD : dump
2522// ----------------------------------------------------------------------------
2523
2524void
2525scfx_rep::dump(::std::ostream &os) const
2526{
2527 os << "scfx_rep" << ::std::endl;
2528 os << "(" << ::std::endl;
2529
2530 os << "mant =" << ::std::endl;
2531 for (int i = size() - 1; i >= 0; i--) {
2532 char buf[BUFSIZ];
2533 std::sprintf(buf, " %d: %10u (%8x)", i,
2534 (int)m_mant[i], (int)m_mant[i]);
2535 os << buf << ::std::endl;
2536 }
2537
2538 os << "wp = " << m_wp << ::std::endl;
2539 os << "sign = " << m_sign << ::std::endl;
2540
2541 os << "state = ";
2542 switch (m_state) {
2543 case normal:
2544 os << "normal";
2545 break;
2546 case infinity:
2547 os << "infinity";
2548 break;
2549 case not_a_number:
2550 os << "not_a_number";
2551 break;
2552 default:
2553 os << "unknown";
2554 }
2555 os << ::std::endl;
2556
2557 os << "msw = " << m_msw << ::std::endl;
2558 os << "lsw = " << m_lsw << ::std::endl;
2559
2560 os << ")" << ::std::endl;
2561}
2562
2563
2564// ----------------------------------------------------------------------------
2565// METHOD : get_type
2566// ----------------------------------------------------------------------------
2567
2568void
2569scfx_rep::get_type(int &wl, int &iwl, sc_enc &enc) const
2570{
2571 if (is_nan() || is_inf()) {
2572 wl = 0;
2573 iwl = 0;
2574 enc = SC_TC_;
2575 return;
2576 }
2577
2578 if (is_zero()) {
2579 wl = 1;
2580 iwl = 1;
2581 enc = SC_US_;
2582 return;
2583 }
2584
2585 int msb = (m_msw - m_wp) * bits_in_word +
2586 scfx_find_msb(m_mant[ m_msw ]) + 1;
2587 while (get_bit(msb) == get_bit(msb - 1)) {
2588 --msb;
2589 }
2590
2591 int lsb = (m_lsw - m_wp) * bits_in_word +
2592 scfx_find_lsb(m_mant[m_lsw]);
2593
2594 if (is_neg()) {
2595 wl = msb - lsb + 1;
2596 iwl = msb + 1;
2597 enc = SC_TC_;
2598 } else {
2599 wl = msb - lsb;
2600 iwl = msb;
2601 enc = SC_US_;
2602 }
2603}
2604
2605
2606// ----------------------------------------------------------------------------
2607// PRIVATE METHOD : round
2608//
2609// Performs convergent rounding (rounding to even) as in floating-point.
2610// ----------------------------------------------------------------------------
2611
2612void
2613scfx_rep::round(int wl)
2614{
2615 // check for special cases
2616
2617 if (is_nan() || is_inf() || is_zero())
2618 return;
2619
2620 // estimate effective wordlength and compare
2621 int wl_effective;
2622 wl_effective = (m_msw - m_lsw + 1) * bits_in_word;
2623 if (wl_effective <= wl)
2624 return;
2625
2626 // calculate effective wordlength and compare
2627 int msb = scfx_find_msb(m_mant[m_msw]);
2628 int lsb = scfx_find_lsb(m_mant[m_lsw]);
2629 wl_effective = (m_msw * bits_in_word + msb) -
2630 (m_lsw * bits_in_word + lsb) + 1;
2631 if (wl_effective <= wl)
2632 return;
2633
2634 // perform rounding
2635 int wi = m_msw - (wl - 1) / bits_in_word;
2636 int bi = msb - (wl - 1) % bits_in_word;
2637 if (bi < 0) {
2638 --wi;
2639 bi += bits_in_word;
2640 }
2641
2642 scfx_index x(wi, bi);
2643
2644 if ((q_bit(x) && ! q_zero(x)) || (q_bit(x) && q_zero(x) && q_odd(x))) {
2645 q_incr(x);
2646 }
2647 q_clear(x);
2648
2649 find_sw();
2650
2651 m_r_flag = true;
2652}
2653
2654} // namespace sc_dt
1968
1969 int n_bits = params.n_bits();
1970
1971 if (n_bits == 0) {
1972 scfx_index x4 = calc_indices(params.iwl());
1973
1974 if (x4.wi() >= size())
1975 resize_to(x4.wi() + 1, 1);
1976
1977 toggle_tc();
1978 if (o_bit_at(x4) != o_bit_at(x))
1979 o_invert(x2);
1980 o_extend(x, SC_TC_);
1981 toggle_tc();
1982 } else if (n_bits == 1) {
1983 toggle_tc();
1984 if (is_neg() != o_bit_at(x))
1985 o_invert(x2);
1986 o_extend(x, SC_TC_);
1987 toggle_tc();
1988 } else if (n_bits < params.wl()) {
1989 scfx_index x3 = calc_indices(params.iwl() - 1 - n_bits);
1990 scfx_index x4 = calc_indices(params.iwl() - n_bits);
1991
1992 // wrap-around least significant 'wl - n_bits' bits;
1993 // saturate most significant 'n_bits' bits
1994 toggle_tc();
1995 if (is_neg() == o_bit_at(x4))
1996 o_invert(x2);
1997 o_set(x, x3, SC_TC_, under);
1998 o_extend(x, SC_TC_);
1999 toggle_tc();
2000 } else {
2001 if (under)
2002 o_set_low(x, SC_TC_);
2003 else
2004 o_set_high(x, x2, SC_TC_);
2005 }
2006 break;
2007 }
2008 default:
2009 ;
2010 }
2011
2012 find_sw();
2013 }
2014}
2015
2016
2017// ----------------------------------------------------------------------------
2018// PUBLIC METHOD : cast
2019//
2020// Performs a destructive cast operation on a scfx_rep.
2021// ----------------------------------------------------------------------------
2022
2023void
2024scfx_rep::cast(const scfx_params &params, bool &q_flag, bool &o_flag)
2025{
2026 q_flag = false;
2027 o_flag = false;
2028
2029 // check for special cases
2030 if (is_zero()) {
2031 if (is_neg())
2032 m_sign = 1;
2033 return;
2034 }
2035
2036 // perform casting
2037 quantization(params, q_flag);
2038 overflow(params, o_flag);
2039
2040 // check for special case: -0
2041 if (is_zero() && is_neg())
2042 m_sign = 1;
2043}
2044
2045
2046// ----------------------------------------------------------------------------
2047// make sure, the two mantissas are aligned
2048// ----------------------------------------------------------------------------
2049
2050void
2051align(const scfx_rep &lhs, const scfx_rep &rhs, int &new_wp,
2052 int &len_mant, scfx_mant_ref &lhs_mant, scfx_mant_ref &rhs_mant)
2053{
2054 bool need_lhs = true;
2055 bool need_rhs = true;
2056
2057 if (lhs.m_wp != rhs.m_wp || lhs.size() != rhs.size()) {
2058 int lower_bound_lhs = lhs.m_lsw - lhs.m_wp;
2059 int upper_bound_lhs = lhs.m_msw - lhs.m_wp;
2060 int lower_bound_rhs = rhs.m_lsw - rhs.m_wp;
2061 int upper_bound_rhs = rhs.m_msw - rhs.m_wp;
2062
2063 int lower_bound = sc_min(lower_bound_lhs, lower_bound_rhs);
2064 int upper_bound = sc_max(upper_bound_lhs, upper_bound_rhs);
2065
2066 new_wp = -lower_bound;
2067 len_mant = sc_max(min_mant, upper_bound - lower_bound + 1);
2068
2069 if (new_wp != lhs.m_wp || len_mant != lhs.size()) {
2070 lhs_mant = lhs.resize(len_mant, new_wp);
2071 need_lhs = false;
2072 }
2073
2074 if (new_wp != rhs.m_wp || len_mant != rhs.size()) {
2075 rhs_mant = rhs.resize(len_mant, new_wp);
2076 need_rhs = false;
2077 }
2078 }
2079
2080 if (need_lhs) {
2081 lhs_mant = lhs.m_mant;
2082 }
2083
2084 if (need_rhs) {
2085 rhs_mant = rhs.m_mant;
2086 }
2087}
2088
2089
2090// ----------------------------------------------------------------------------
2091// compare two mantissas
2092// ----------------------------------------------------------------------------
2093
2094int
2095compare_msw_ff(const scfx_rep &lhs, const scfx_rep &rhs)
2096{
2097 // special case: rhs.m_mant[rhs.m_msw + 1] == 1
2098 if (rhs.m_msw < rhs.size() - 1 && rhs.m_mant[rhs.m_msw + 1 ] != 0) {
2099 return -1;
2100 }
2101
2102 int lhs_size = lhs.m_msw - lhs.m_lsw + 1;
2103 int rhs_size = rhs.m_msw - rhs.m_lsw + 1;
2104
2105 int size = sc_min(lhs_size, rhs_size);
2106
2107 int lhs_index = lhs.m_msw;
2108 int rhs_index = rhs.m_msw;
2109
2110 int i;
2111
2112 for (i = 0;
2113 i < size && lhs.m_mant[lhs_index] == rhs.m_mant[rhs_index];
2114 i++) {
2115 lhs_index--;
2116 rhs_index--;
2117 }
2118
2119 if (i == size) {
2120 if (lhs_size == rhs_size) {
2121 return 0;
2122 }
2123
2124 if (lhs_size < rhs_size) {
2125 return -1;
2126 } else {
2127 return 1;
2128 }
2129 }
2130
2131 if (lhs.m_mant[lhs_index] < rhs.m_mant[rhs_index]) {
2132 return -1;
2133 } else {
2134 return 1;
2135 }
2136}
2137
2138
2139// ----------------------------------------------------------------------------
2140// divide the mantissa by ten
2141// ----------------------------------------------------------------------------
2142
2143unsigned int
2144scfx_rep::divide_by_ten()
2145{
2146#if defined(SC_BOOST_BIG_ENDIAN)
2147 half_word *hw = (half_word *)&m_mant[m_msw];
2148#elif defined(SC_BOOST_LITTLE_ENDIAN)
2149 half_word *hw = ((half_word *)&m_mant[m_msw]) + 1;
2150#endif
2151
2152 unsigned int remainder = 0;
2153
2154 word_short ls;
2155 ls.l = 0;
2156
2157#if defined(SC_BOOST_BIG_ENDIAN)
2158 for (int i = 0, end = (m_msw - m_wp + 1) * 2; i < end; i++) {
2159#elif defined(SC_BOOST_LITTLE_ENDIAN)
2160 for (int i = 0, end = -(m_msw - m_wp + 1) * 2; i > end; i--) {
2161#endif
2162 ls.s.u = static_cast<half_word>(remainder);
2163 ls.s.l = hw[i];
2164 remainder = ls.l % 10;
2165 ls.l /= 10;
2166 hw[i] = ls.s.l;
2167 }
2168
2169 return remainder;
2170}
2171
2172
2173// ----------------------------------------------------------------------------
2174// multiply the mantissa by ten
2175// ----------------------------------------------------------------------------
2176
2177void
2178scfx_rep::multiply_by_ten()
2179{
2180 int size = m_mant.size() + 1;
2181
2182 scfx_mant mant8(size);
2183 scfx_mant mant2(size);
2184
2185 size--;
2186
2187 mant8[size] = (m_mant[size - 1] >> (bits_in_word - 3));
2188 mant2[size] = (m_mant[size - 1] >> (bits_in_word - 1));
2189
2190 while (--size) {
2191 mant8[size] = (m_mant[size] << 3) |
2192 (m_mant[size - 1] >> (bits_in_word - 3));
2193 mant2[size] = (m_mant[size] << 1) |
2194 (m_mant[size - 1] >> (bits_in_word - 1));
2195 }
2196
2197 mant8[0] = (m_mant[0] << 3);
2198 mant2[0] = (m_mant[0] << 1);
2199
2200 add_mants(m_mant.size(), m_mant, mant8, mant2);
2201}
2202
2203
2204// ----------------------------------------------------------------------------
2205// normalize
2206// ----------------------------------------------------------------------------
2207
2208void
2209scfx_rep::normalize(int exponent)
2210{
2211 int shift = exponent % bits_in_word;
2212 if (shift < 0) {
2213 shift += bits_in_word;
2214 }
2215
2216 if (shift) {
2217 shift_left(shift);
2218 }
2219
2220 find_sw();
2221
2222 m_wp = (shift - exponent) / bits_in_word;
2223}
2224
2225
2226// ----------------------------------------------------------------------------
2227// return a new mantissa that is aligned and resized
2228// ----------------------------------------------------------------------------
2229
2230scfx_mant *
2231scfx_rep::resize(int new_size, int new_wp) const
2232{
2233 scfx_mant *result = new scfx_mant(new_size);
2234
2235 result->clear();
2236
2237 int shift = new_wp - m_wp;
2238
2239 for (int j = m_lsw; j <= m_msw; j++) {
2240 (*result)[j + shift] = m_mant[j];
2241 }
2242
2243 return result;
2244}
2245
2246
2247// ----------------------------------------------------------------------------
2248// set a single bit
2249// ----------------------------------------------------------------------------
2250
2251void
2252scfx_rep::set_bin(int i)
2253{
2254 m_mant[i >> 5] |= 1 << (i & 31);
2255}
2256
2257
2258// ----------------------------------------------------------------------------
2259// set three bits
2260// ----------------------------------------------------------------------------
2261
2262void
2263scfx_rep::set_oct(int i, int n)
2264{
2265 if (n & 1) {
2266 m_mant[i >> 5] |= 1 << (i & 31);
2267 }
2268 i++;
2269 if (n & 2) {
2270 m_mant[i >> 5] |= 1 << (i & 31);
2271 }
2272 i++;
2273 if (n & 4) {
2274 m_mant[i >> 5] |= 1 << (i & 31);
2275 }
2276}
2277
2278
2279// ----------------------------------------------------------------------------
2280// set four bits
2281// ----------------------------------------------------------------------------
2282
2283void
2284scfx_rep::set_hex(int i, int n)
2285{
2286 if (n & 1) {
2287 m_mant[i >> 5] |= 1 << (i & 31);
2288 }
2289 i++;
2290 if (n & 2) {
2291 m_mant[i >> 5] |= 1 << (i & 31);
2292 }
2293 i++;
2294 if (n & 4) {
2295 m_mant[i >> 5] |= 1 << (i & 31);
2296 }
2297 i++;
2298 if (n & 8) {
2299 m_mant[i >> 5] |= 1 << (i & 31);
2300 }
2301}
2302
2303
2304// ----------------------------------------------------------------------------
2305// PRIVATE METHOD : shift_left
2306//
2307// Shifts a scfx_rep to the left by a MAXIMUM of bits_in_word - 1 bits.
2308// ----------------------------------------------------------------------------
2309
2310void
2311scfx_rep::shift_left(int n)
2312{
2313 if (n != 0) {
2314 int shift_left = n;
2315 int shift_right = bits_in_word - n;
2316
2317 SC_ASSERT_(!(m_mant[size() - 1] >> shift_right),
2318 "shift_left overflow");
2319
2320 for (int i = size() - 1; i > 0; i--) {
2321 m_mant[i] = (m_mant[i] << shift_left) |
2322 (m_mant[i - 1] >> shift_right);
2323 }
2324 m_mant[0] <<= shift_left;
2325 }
2326}
2327
2328
2329// ----------------------------------------------------------------------------
2330// PRIVATE METHOD : shift_right
2331//
2332// Shifts a scfx_rep to the right by a MAXIMUM of bits_in_word - 1 bits.
2333// ----------------------------------------------------------------------------
2334
2335void
2336scfx_rep::shift_right(int n)
2337{
2338 if (n != 0) {
2339 int shift_left = bits_in_word - n;
2340 int shift_right = n;
2341
2342 SC_ASSERT_(!(m_mant[0] << shift_left), "shift_right overflow");
2343
2344 for (int i = 0; i < size() - 1; i++) {
2345 m_mant[i] = (m_mant[i] >> shift_right) |
2346 (m_mant[i + 1] << shift_left);
2347 }
2348 m_mant[size() - 1] >>= shift_right;
2349 }
2350}
2351
2352
2353// ----------------------------------------------------------------------------
2354// METHOD : get_bit
2355//
2356// Tests a bit, in two's complement.
2357// ----------------------------------------------------------------------------
2358
2359bool
2360scfx_rep::get_bit(int i) const
2361{
2362 if (!is_normal())
2363 return false;
2364
2365 scfx_index x = calc_indices(i);
2366
2367 if (x.wi() >= size())
2368 return is_neg();
2369
2370 if (x.wi() < 0)
2371 return false;
2372
2373 const_cast<scfx_rep*>(this)->toggle_tc();
2374
2375 bool result = (m_mant[x.wi()] & (1 << x.bi())) != 0;
2376
2377 const_cast<scfx_rep *>(this)->toggle_tc();
2378
2379 return result;
2380}
2381
2382
2383// ----------------------------------------------------------------------------
2384// METHOD : set
2385//
2386// Sets a bit, in two's complement, between iwl-1 and -fwl.
2387// ----------------------------------------------------------------------------
2388
2389bool
2390scfx_rep::set(int i, const scfx_params &params)
2391{
2392 if (!is_normal())
2393 return false;
2394
2395 scfx_index x = calc_indices(i);
2396
2397 if (x.wi() >= size()) {
2398 if (is_neg())
2399 return true;
2400 else
2401 resize_to(x.wi() + 1, 1);
2402 } else if (x.wi() < 0) {
2403 resize_to(size() - x.wi(), -1);
2404 x.wi(0);
2405 }
2406
2407 toggle_tc();
2408
2409 m_mant[x.wi()] |= 1 << x.bi();
2410
2411 if (i == params.iwl() - 1)
2412 o_extend(x, params.enc()); // sign extension
2413
2414 toggle_tc();
2415
2416 find_sw();
2417
2418 return true;
2419}
2420
2421
2422// ----------------------------------------------------------------------------
2423// METHOD : clear
2424//
2425// Clears a bit, in two's complement, between iwl-1 and -fwl.
2426// ----------------------------------------------------------------------------
2427
2428bool
2429scfx_rep::clear(int i, const scfx_params &params)
2430{
2431 if (!is_normal())
2432 return false;
2433
2434 scfx_index x = calc_indices(i);
2435
2436 if (x.wi() >= size()) {
2437 if (!is_neg())
2438 return true;
2439 else
2440 resize_to(x.wi() + 1, 1);
2441 } else if (x.wi() < 0) {
2442 return true;
2443 }
2444
2445 toggle_tc();
2446
2447 m_mant[x.wi()] &= ~(1 << x.bi());
2448
2449 if (i == params.iwl() - 1)
2450 o_extend(x, params.enc()); // sign extension
2451
2452 toggle_tc();
2453
2454 find_sw();
2455
2456 return true;
2457}
2458
2459
2460// ----------------------------------------------------------------------------
2461// METHOD : get_slice
2462// ----------------------------------------------------------------------------
2463
2464bool
2465scfx_rep::get_slice(int i, int j, const scfx_params &, sc_bv_base &bv) const
2466{
2467 if (is_nan() || is_inf())
2468 return false;
2469
2470 // get the bits
2471
2472 int l = j;
2473 for (int k = 0; k < bv.length(); ++k) {
2474 bv[k] = get_bit(l);
2475
2476 if (i >= j)
2477 ++l;
2478 else
2479 --l;
2480 }
2481
2482 return true;
2483}
2484
2485bool
2486scfx_rep::set_slice(int i, int j, const scfx_params &params,
2487 const sc_bv_base &bv)
2488{
2489 if (is_nan() || is_inf())
2490 return false;
2491
2492 // set the bits
2493 int l = j;
2494 for (int k = 0; k < bv.length(); ++k) {
2495 if (bv[k].to_bool())
2496 set(l, params);
2497 else
2498 clear(l, params);
2499
2500 if (i >= j)
2501 ++l;
2502 else
2503 --l;
2504 }
2505
2506 return true;
2507}
2508
2509
2510// ----------------------------------------------------------------------------
2511// METHOD : print
2512// ----------------------------------------------------------------------------
2513
2514void
2515scfx_rep::print(::std::ostream &os) const
2516{
2517 os << to_string(SC_DEC, -1, SC_E);
2518}
2519
2520
2521// ----------------------------------------------------------------------------
2522// METHOD : dump
2523// ----------------------------------------------------------------------------
2524
2525void
2526scfx_rep::dump(::std::ostream &os) const
2527{
2528 os << "scfx_rep" << ::std::endl;
2529 os << "(" << ::std::endl;
2530
2531 os << "mant =" << ::std::endl;
2532 for (int i = size() - 1; i >= 0; i--) {
2533 char buf[BUFSIZ];
2534 std::sprintf(buf, " %d: %10u (%8x)", i,
2535 (int)m_mant[i], (int)m_mant[i]);
2536 os << buf << ::std::endl;
2537 }
2538
2539 os << "wp = " << m_wp << ::std::endl;
2540 os << "sign = " << m_sign << ::std::endl;
2541
2542 os << "state = ";
2543 switch (m_state) {
2544 case normal:
2545 os << "normal";
2546 break;
2547 case infinity:
2548 os << "infinity";
2549 break;
2550 case not_a_number:
2551 os << "not_a_number";
2552 break;
2553 default:
2554 os << "unknown";
2555 }
2556 os << ::std::endl;
2557
2558 os << "msw = " << m_msw << ::std::endl;
2559 os << "lsw = " << m_lsw << ::std::endl;
2560
2561 os << ")" << ::std::endl;
2562}
2563
2564
2565// ----------------------------------------------------------------------------
2566// METHOD : get_type
2567// ----------------------------------------------------------------------------
2568
2569void
2570scfx_rep::get_type(int &wl, int &iwl, sc_enc &enc) const
2571{
2572 if (is_nan() || is_inf()) {
2573 wl = 0;
2574 iwl = 0;
2575 enc = SC_TC_;
2576 return;
2577 }
2578
2579 if (is_zero()) {
2580 wl = 1;
2581 iwl = 1;
2582 enc = SC_US_;
2583 return;
2584 }
2585
2586 int msb = (m_msw - m_wp) * bits_in_word +
2587 scfx_find_msb(m_mant[ m_msw ]) + 1;
2588 while (get_bit(msb) == get_bit(msb - 1)) {
2589 --msb;
2590 }
2591
2592 int lsb = (m_lsw - m_wp) * bits_in_word +
2593 scfx_find_lsb(m_mant[m_lsw]);
2594
2595 if (is_neg()) {
2596 wl = msb - lsb + 1;
2597 iwl = msb + 1;
2598 enc = SC_TC_;
2599 } else {
2600 wl = msb - lsb;
2601 iwl = msb;
2602 enc = SC_US_;
2603 }
2604}
2605
2606
2607// ----------------------------------------------------------------------------
2608// PRIVATE METHOD : round
2609//
2610// Performs convergent rounding (rounding to even) as in floating-point.
2611// ----------------------------------------------------------------------------
2612
2613void
2614scfx_rep::round(int wl)
2615{
2616 // check for special cases
2617
2618 if (is_nan() || is_inf() || is_zero())
2619 return;
2620
2621 // estimate effective wordlength and compare
2622 int wl_effective;
2623 wl_effective = (m_msw - m_lsw + 1) * bits_in_word;
2624 if (wl_effective <= wl)
2625 return;
2626
2627 // calculate effective wordlength and compare
2628 int msb = scfx_find_msb(m_mant[m_msw]);
2629 int lsb = scfx_find_lsb(m_mant[m_lsw]);
2630 wl_effective = (m_msw * bits_in_word + msb) -
2631 (m_lsw * bits_in_word + lsb) + 1;
2632 if (wl_effective <= wl)
2633 return;
2634
2635 // perform rounding
2636 int wi = m_msw - (wl - 1) / bits_in_word;
2637 int bi = msb - (wl - 1) % bits_in_word;
2638 if (bi < 0) {
2639 --wi;
2640 bi += bits_in_word;
2641 }
2642
2643 scfx_index x(wi, bi);
2644
2645 if ((q_bit(x) && ! q_zero(x)) || (q_bit(x) && q_zero(x) && q_odd(x))) {
2646 q_incr(x);
2647 }
2648 q_clear(x);
2649
2650 find_sw();
2651
2652 m_r_flag = true;
2653}
2654
2655} // namespace sc_dt