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.h - 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// $Log: scfx_rep.h,v $ 40// Revision 1.6 2011/08/24 22:05:43 acg 41// Torsten Maehne: initialization changes to remove warnings. 42// 43// Revision 1.5 2011/07/25 10:20:29 acg 44// Andy Goodrich: check in aftermath of call to automake. 45// 46// Revision 1.4 2010/12/07 20:09:08 acg 47// Andy Goodrich: Philipp Hartmann's constructor disambiguation fix 48// 49// Revision 1.3 2010/08/03 15:54:52 acg 50// Andy Goodrich: formatting. 51// 52// Revision 1.2 2010/03/15 18:29:01 acg 53// Andy Goodrich: Moved default argument specifications from friend 54// declarations to the actual function signatures. 55// 56// Revision 1.1.1.1 2006/12/15 20:20:04 acg 57// SystemC 2.3 58// 59// Revision 1.4 2006/03/13 20:24:27 acg 60// Andy Goodrich: Addition of function declarations, e.g., neg_scfx_rep(), 61// to keep gcc 4.x happy. 62// 63// Revision 1.3 2006/01/13 18:53:58 acg 64// Andy Goodrich: added $Log command so that CVS comments are reproduced in 65// the source. 66// 67 68#ifndef __SYSTEMC_EXT_DT_FX_SCFX_REP_HH__ 69#define __SYSTEMC_EXT_DT_FX_SCFX_REP_HH__ 70 71#include <climits> 72 73#include "scfx_mant.hh" 74#include "scfx_params.hh" 75#include "scfx_string.hh" 76 77namespace sc_dt 78{ 79 80// classes defined in this module 81class scfx_index; 82class scfx_rep; 83 84// forward class declarations 85class sc_bv_base; 86class sc_signed; 87class sc_unsigned; 88 89// function declarations 90void multiply(scfx_rep &, const scfx_rep &, const scfx_rep &, 91 int max_wl=SC_DEFAULT_MAX_WL_); 92scfx_rep *neg_scfx_rep(const scfx_rep &); 93scfx_rep *mult_scfx_rep(const scfx_rep &, const scfx_rep &, 94 int max_wl=SC_DEFAULT_MAX_WL_); 95scfx_rep *div_scfx_rep(const scfx_rep &, const scfx_rep &, 96 int max_wl=SC_DEFAULT_DIV_WL_); 97scfx_rep *add_scfx_rep(const scfx_rep &, const scfx_rep &, 98 int max_wl=SC_DEFAULT_MAX_WL_); 99scfx_rep *sub_scfx_rep(const scfx_rep &, const scfx_rep &, 100 int max_wl=SC_DEFAULT_MAX_WL_); 101scfx_rep *lsh_scfx_rep(const scfx_rep &, int); 102scfx_rep *rsh_scfx_rep(const scfx_rep &, int); 103int cmp_scfx_rep(const scfx_rep &, const scfx_rep &); 104 105const int min_mant = 4; 106 107const int bits_in_int = sizeof(int) * CHAR_BIT; 108const int bits_in_word = sizeof(word) * CHAR_BIT; 109 110 111// ---------------------------------------------------------------------------- 112// CLASS : scfx_index 113// ---------------------------------------------------------------------------- 114 115class scfx_index 116{ 117 public: 118 scfx_index(int wi_, int bi_) : m_wi(wi_), m_bi(bi_) {} 119 120 int wi() const { return m_wi; } 121 int bi() const { return m_bi; } 122 123 void wi(int wi_) { m_wi = wi_; } 124 125 private: 126 int m_wi; 127 int m_bi; 128}; 129 130 131// ---------------------------------------------------------------------------- 132// CLASS : scfx_rep 133// 134// Arbitrary-precision fixed-point implementation class. 135// ---------------------------------------------------------------------------- 136 137class scfx_rep 138{ 139 enum state 140 { 141 normal, 142 infinity, 143 not_a_number 144 }; 145 146 public: 147 // constructors 148 scfx_rep(); 149 explicit scfx_rep(int); 150 explicit scfx_rep(unsigned int); 151 explicit scfx_rep(long); 152 explicit scfx_rep(unsigned long); 153 explicit scfx_rep(double); 154 explicit scfx_rep(const char *); 155 explicit scfx_rep(int64); 156 explicit scfx_rep(uint64); 157 explicit scfx_rep(const sc_signed &); 158 explicit scfx_rep(const sc_unsigned &); 159 160 // copy constructor 161 scfx_rep(const scfx_rep &); 162 163 // destructor 164 ~scfx_rep(); 165 166 void *operator new (std::size_t); 167 void operator delete (void *, std::size_t); 168 169 void from_string(const char *, int); 170 171 double to_double() const; 172 uint64 to_uint64() const; 173 174 const char *to_string(sc_numrep, int, sc_fmt, 175 const scfx_params * =0) const; 176 177 // assignment operator 178 void operator = (const scfx_rep &); 179 180 friend void multiply( scfx_rep&, const scfx_rep&, const scfx_rep&, int ); 181 182 friend scfx_rep *neg_scfx_rep(const scfx_rep &); 183 friend scfx_rep *mult_scfx_rep(const scfx_rep &, const scfx_rep &, int); 184 friend scfx_rep *div_scfx_rep(const scfx_rep &, const scfx_rep &, int); 185 friend scfx_rep *add_scfx_rep(const scfx_rep &, const scfx_rep &, int); 186 friend scfx_rep *sub_scfx_rep(const scfx_rep &, const scfx_rep &, int); 187 friend scfx_rep *lsh_scfx_rep(const scfx_rep &, int); 188 friend scfx_rep *rsh_scfx_rep(const scfx_rep &, int); 189 190 void lshift(int); 191 void rshift(int); 192 193 friend int cmp_scfx_rep(const scfx_rep &, const scfx_rep &); 194 195 void cast(const scfx_params &, bool &, bool &); 196 197 bool is_neg() const; 198 bool is_zero() const; 199 bool is_nan() const; 200 bool is_inf() const; 201 bool is_normal() const; 202 203 void set_zero(int=1); 204 void set_nan(); 205 void set_inf(int); 206 207 bool get_bit(int) const; 208 bool set(int, const scfx_params &); 209 bool clear(int, const scfx_params &); 210 211 bool get_slice(int, int, const scfx_params &, sc_bv_base &) const; 212 bool set_slice(int, int, const scfx_params &, const sc_bv_base &); 213 214 void print(::std::ostream &) const; 215 void dump(::std::ostream &) const; 216 217 void get_type(int &, int &, sc_enc &) const; 218 219 friend scfx_rep *quantization_scfx_rep( 220 const scfx_rep &, const scfx_params &, bool &); 221 friend scfx_rep *overflow_scfx_rep( 222 const scfx_rep &, const scfx_params &, bool &); 223 224 bool rounding_flag() const; 225 226 private: 227 friend void align(const scfx_rep &, const scfx_rep &, int &, int &, 228 scfx_mant_ref &, scfx_mant_ref &); 229 friend int compare_msw(const scfx_rep &, const scfx_rep &); 230 friend int compare_msw_ff(const scfx_rep &lhs, const scfx_rep &rhs); 231 unsigned int divide_by_ten(); 232 int find_lsw() const; 233 int find_msw() const; 234 void find_sw(); 235 void multiply_by_ten(); 236 void normalize(int); 237 scfx_mant *resize(int, int) const; 238 void set_bin(int); 239 void set_oct(int, int); 240 void set_hex(int, int); 241 void shift_left(int); 242 void shift_right(int); 243 244 const scfx_index calc_indices(int) const; 245 246 void o_extend(const scfx_index &, sc_enc); 247 bool o_bit_at(const scfx_index &) const; 248 bool o_zero_left(const scfx_index &) const; 249 bool o_zero_right(const scfx_index &) const; 250 void o_set_low(const scfx_index &, sc_enc); 251 void o_set_high(const scfx_index &, const scfx_index &, sc_enc, int=1); 252 void o_set(const scfx_index &, const scfx_index &, sc_enc, bool); 253 void o_invert(const scfx_index &); 254 bool q_bit(const scfx_index &) const; 255 void q_clear(const scfx_index &); 256 void q_incr(const scfx_index &); 257 bool q_odd(const scfx_index &) const; 258 bool q_zero(const scfx_index &) const; 259 260 void resize_to(int, int=0); 261 int size() const; 262 void toggle_tc(); 263 264 friend void print_dec(scfx_string &, const scfx_rep &, int, sc_fmt); 265 friend void print_other(scfx_string &, const scfx_rep &, sc_numrep, int, 266 sc_fmt, const scfx_params *); 267 268 void quantization(const scfx_params &, bool &); 269 void overflow(const scfx_params &, bool &); 270 271 friend int compare_abs(const scfx_rep &, const scfx_rep &); 272 273 void round(int); 274 275 private: 276 scfx_mant m_mant; // mantissa (bits of the value). 277 int m_wp; // index of highest order word in value. 278 int m_sign; // sign of value. 279 state m_state; // value state, e.g., normal, inf, etc. 280 int m_msw; // index of most significant non-zero word. 281 int m_lsw; // index of least significant non-zero word. 282 bool m_r_flag; // true if rounding occurred. 283}; 284 285 286// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 287 288inline void 289scfx_rep::set_zero(int sign) 290{ 291 m_mant.clear(); 292 m_wp = m_msw = m_lsw = 0; 293 m_sign = sign; 294 m_state = normal; 295} 296 297inline void 298scfx_rep::set_nan() 299{ 300 m_mant.resize_to(min_mant); 301 m_state = not_a_number; 302} 303 304inline void 305scfx_rep::set_inf(int sign) 306{ 307 m_mant.resize_to(min_mant); 308 m_state = infinity; 309 m_sign = sign; 310} 311 312// constructors 313inline scfx_rep::scfx_rep(const char *s) : 314 m_mant(min_mant), m_wp(2), m_sign(1), m_state(normal), 315 m_msw(0), m_lsw(0), m_r_flag(false) 316{ 317 from_string(s, SC_DEFAULT_CTE_WL_); 318} 319 320// destructor 321inline scfx_rep::~scfx_rep() {} 322 323// assignment operator 324inline void 325scfx_rep::operator = (const scfx_rep &f) 326{ 327 if (&f != this) { 328 m_mant = f.m_mant; 329 m_wp = f.m_wp; 330 m_sign = f.m_sign; 331 m_state = f.m_state; 332 m_msw = f.m_msw; 333 m_lsw = f.m_lsw; 334 round(SC_DEFAULT_MAX_WL_); 335 } 336} 337 338inline scfx_rep * 339neg_scfx_rep(const scfx_rep &a) 340{ 341 scfx_rep &c = *new scfx_rep(a); 342 c.m_sign = - c.m_sign; 343 return &c; 344} 345 346inline scfx_rep * 347mult_scfx_rep(const scfx_rep &a, const scfx_rep &b, int max_wl) 348{ 349 scfx_rep &c = *new scfx_rep; 350 sc_dt::multiply(c, a, b, max_wl); 351 return &c; 352} 353 354inline scfx_rep * 355lsh_scfx_rep(const scfx_rep &a, int b) 356{ 357 scfx_rep &c = *new scfx_rep(a); 358 c.lshift(b); 359 return &c; 360} 361 362inline scfx_rep * 363rsh_scfx_rep(const scfx_rep &a, int b) 364{ 365 scfx_rep &c = *new scfx_rep(a); 366 c.rshift(b); 367 return &c; 368} 369 370inline int scfx_rep::size() const { return m_mant.size(); } 371 372inline bool scfx_rep::is_neg() const { return (m_sign == -1); } 373 374inline bool 375scfx_rep::is_zero() const 376{ 377 if (m_state != normal) 378 return false; 379 380 for (int i = 0; i < size(); i++) { 381 if (m_mant[i]) 382 return false; 383 } 384 385 return true; 386} 387 388inline bool scfx_rep::is_nan() const { return (m_state == not_a_number); } 389 390inline bool scfx_rep::is_inf() const { return (m_state == infinity); } 391 392inline bool scfx_rep::is_normal() const { return (m_state == normal); } 393 394inline scfx_rep * 395quantization_scfx_rep(const scfx_rep &a, const scfx_params ¶ms, 396 bool &q_flag) 397{ 398 scfx_rep &c = *new scfx_rep(a); 399 c.quantization(params, q_flag); 400 return &c; 401} 402 403inline scfx_rep * 404overflow_scfx_rep(const scfx_rep &a, const scfx_params ¶ms, bool &o_flag) 405{ 406 scfx_rep& c = *new scfx_rep(a); 407 c.overflow(params, o_flag); 408 return &c; 409} 410 411inline bool scfx_rep::rounding_flag() const { return m_r_flag; } 412 413inline void 414scfx_rep::resize_to(int new_size, int restore) 415{ 416 if (restore == -1) { 417 int size_incr = new_size - size(); 418 m_wp += size_incr; 419 m_msw += size_incr; 420 m_lsw += size_incr; 421 } 422 m_mant.resize_to(new_size, restore); 423} 424 425inline const scfx_index 426scfx_rep::calc_indices(int n) const 427{ 428 int wi = n / bits_in_word + m_wp; 429 int bi = n % bits_in_word; 430 431 if (bi < 0) { 432 bi += bits_in_word; 433 -- wi; 434 } 435 436 return scfx_index(wi, bi); 437} 438 439inline void 440scfx_rep::o_extend(const scfx_index &x, sc_enc enc) 441{ 442 int wi = x.wi(); 443 int bi = x.bi(); 444 445 SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); 446 447 if (enc == SC_US_ || (m_mant[wi] & (((word)1) << bi)) == 0) { 448 if (bi != bits_in_word - 1) 449 m_mant[wi] &= ~(((word)-1) << (bi + 1)); 450 for (int i = wi + 1; i < size(); ++i) 451 m_mant[i] = 0; 452 m_sign = 1; 453 } else { 454 if (bi != bits_in_word - 1) 455 m_mant[wi] |= (((word)-1) << (bi + 1)); 456 for (int i = wi + 1; i < size(); ++i) 457 m_mant[i] = static_cast<word>(-1); 458 m_sign = -1; 459 } 460} 461 462inline bool 463scfx_rep::o_bit_at(const scfx_index &x) const 464{ 465 int wi = x.wi(); 466 int bi = x.bi(); 467 468 SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); 469 470 return (m_mant[wi] & (((word)1) << bi)) != 0; 471} 472 473inline bool 474scfx_rep::o_zero_left(const scfx_index &x) const 475{ 476 int wi = x.wi(); 477 int bi = x.bi(); 478 479 SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); 480 481 bool zero = true; 482 if (bi != bits_in_word - 1) 483 zero = (m_mant[wi] & (((word)-1) << (bi + 1))) == 0; 484 for (int i = wi + 1; i < size(); ++i) 485 zero = zero && m_mant[i] == 0; 486 487 return zero; 488} 489 490inline bool 491scfx_rep::o_zero_right(const scfx_index &x) const 492{ 493 int wi = x.wi(); 494 int bi = x.bi(); 495 496 SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); 497 498 bool zero = (m_mant[wi] & ~(((word)-1) << bi)) == 0; 499 for (int i = wi - 1; i >= 0; --i) 500 zero = zero && m_mant[i] == 0; 501 502 return zero; 503} 504 505inline void 506scfx_rep::o_set_low(const scfx_index &x, sc_enc enc) 507{ 508 int wi = x.wi(); 509 int bi = x.bi(); 510 511 SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); 512 513 m_mant.clear(); 514 515 if (enc == SC_TC_) { 516 m_mant[wi] |= (((word)1) << bi); 517 m_sign = -1; 518 } else { 519 m_sign = 1; 520 } 521} 522 523inline void 524scfx_rep::o_set_high(const scfx_index &x, const scfx_index &x2, 525 sc_enc enc, int sign) 526{ 527 int wi = x.wi(); 528 int bi = x.bi(); 529 int wi2 = x2.wi(); 530 int bi2 = x2.bi(); 531 532 SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); 533 SC_ASSERT_(wi2 >= 0 && wi2 < size(), "word index out of range"); 534 535 int i; 536 537 for (i = 0; i < size(); ++i) 538 m_mant[i] = static_cast<word>(-1); 539 540 m_mant[wi] &= ~(((word)-1) << bi); 541 for (i = wi + 1; i < size(); ++i) 542 m_mant[i] = 0; 543 544 m_mant[wi2] &= (((word)-1) << bi2); 545 for (i = wi2 - 1; i >= 0; --i) 546 m_mant[i] = 0; 547 548 if (enc == SC_TC_) { 549 m_sign = sign; 550 } else { 551 m_mant[wi] |= (((word)1) << bi); 552 m_sign = 1; 553 } 554} 555 556inline void 557scfx_rep::o_set(const scfx_index &x, const scfx_index &x3, sc_enc enc, 558 bool under) 559{ 560 int wi = x.wi(); 561 int bi = x.bi(); 562 int wi3 = x3.wi(); 563 int bi3 = x3.bi(); 564 565 SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); 566 SC_ASSERT_(wi3 >= 0 && wi3 < size(), "word index out of range"); 567 568 if (bi3 != bits_in_word - 1) { 569 if (under) 570 m_mant[wi3] &= ~(((word)-1) << (bi3 + 1)); 571 else 572 m_mant[wi3] |= (((word)-1) << (bi3 + 1)); 573 } 574 for (int i = wi3 + 1; i < size(); ++i) { 575 if (under) 576 m_mant[i] = 0; 577 else 578 m_mant[i] = static_cast<word>(-1); 579 } 580 581 if (enc == SC_TC_) { 582 if (under) 583 m_mant[wi] |= (((word)1) << bi); 584 else 585 m_mant[wi] &= ~(((word)1) << bi); 586 } 587} 588 589inline void 590scfx_rep::o_invert(const scfx_index &x2) 591{ 592 int wi2 = x2.wi(); 593 int bi2 = x2.bi(); 594 595 m_mant[wi2] ^= (((word)-1) << bi2); 596 for (int i = wi2 + 1; i < size(); ++i) 597 m_mant[i] = ~ m_mant[i]; 598} 599 600inline bool 601scfx_rep::q_bit(const scfx_index &x) const 602{ 603 int wi = x.wi(); 604 int bi = x.bi(); 605 606 SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); 607 608 if (bi != 0) 609 return (m_mant[wi] & (((word)1) << (bi - 1))) != 0; 610 else if (wi != 0) 611 return (m_mant[wi - 1] & (((word)1) << (bits_in_word - 1))) != 0; 612 else 613 return false; 614} 615 616inline void 617scfx_rep::q_clear(const scfx_index &x) 618{ 619 int wi = x.wi(); 620 int bi = x.bi(); 621 622 SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); 623 624 m_mant[wi] &= (((word)-1) << bi); 625 for (int i = wi - 1; i >= 0; --i) 626 m_mant[i] = 0; 627} 628 629inline void 630scfx_rep::q_incr(const scfx_index &x) 631{ 632 int wi = x.wi(); 633 int bi = x.bi(); 634 635 SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); 636 637 word old_val = m_mant[wi]; 638 m_mant[wi] += (((word)1) << bi); 639 if (m_mant[wi] <= old_val) { 640 if (wi + 1 == size()) 641 resize_to(size() + 1, 1); 642 643 for (int i = wi + 1; i < size(); ++i) { 644 if (++m_mant[i] != 0) 645 break; 646 } 647 } 648} 649 650inline bool 651scfx_rep::q_odd(const scfx_index &x) const 652{ 653 int wi = x.wi(); 654 int bi = x.bi(); 655 656 SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); 657 658 return (m_mant[wi] & (((word)1) << bi)) != 0; 659} 660 661inline bool 662scfx_rep::q_zero(const scfx_index &x) const 663{ 664 int wi = x.wi(); 665 int bi = x.bi(); 666 667 SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); 668 669 bool zero; 670 671 if (bi != 0) { 672 zero = (m_mant[wi] & ~(((word)-1) << (bi - 1))) == 0; 673 for (int i = wi - 1; i >= 0; --i) 674 zero = zero && m_mant[i] == 0; 675 } else if (wi != 0) { 676 zero = (m_mant[wi - 1] & ~( ((word)-1) << (bits_in_word - 1))) == 0; 677 for (int i = wi - 2; i >= 0; --i) 678 zero = zero && m_mant[i] == 0; 679 } else { 680 zero = true; 681 } 682 683 return zero; 684} 685 686inline int 687scfx_rep::find_lsw() const 688{ 689 for (int i = 0; i < size(); i++) { 690 if (m_mant[i]) 691 return i; 692 } 693 return 0; 694} 695 696inline int 697scfx_rep::find_msw() const 698{ 699 for (int i = size() - 1; i >= 0; i--) { 700 if (m_mant[i]) 701 return i; 702 } 703 return 0; 704} 705 706inline void 707scfx_rep::find_sw() 708{ 709 m_lsw = find_lsw(); 710 m_msw = find_msw(); 711} 712 713inline void 714scfx_rep::toggle_tc() 715{ 716 if (is_neg()) { 717 complement(m_mant, m_mant, m_mant.size()); 718 inc(m_mant); 719 } 720} 721 722} // namespace sc_dt 723 724#endif // __SYSTEMC_EXT_DT_FX_SCFX_REP_HH__ 725