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 SCFX_REP_H 69#define SCFX_REP_H 70 71 72#include <climits> 73 74#include "sysc/datatypes/fx/scfx_mant.h" 75#include "sysc/datatypes/fx/scfx_params.h" 76#include "sysc/datatypes/fx/scfx_string.h" 77 78 79namespace sc_dt 80{ 81 82// classes defined in this module 83class scfx_index; 84class scfx_rep; 85 86// forward class declarations 87class sc_bv_base; 88class sc_signed; 89class sc_unsigned; 90 91// function declarations 92void multiply( scfx_rep&, const scfx_rep&, const scfx_rep&, 93 int max_wl = SC_DEFAULT_MAX_WL_ ); 94scfx_rep* neg_scfx_rep( const scfx_rep& ); 95scfx_rep* mult_scfx_rep( const scfx_rep&, const scfx_rep&, 96 int max_wl = SC_DEFAULT_MAX_WL_ ); 97scfx_rep* div_scfx_rep( const scfx_rep&, const scfx_rep&, 98 int max_wl = SC_DEFAULT_DIV_WL_ ); 99scfx_rep* add_scfx_rep( const scfx_rep&, const scfx_rep&, 100 int max_wl = SC_DEFAULT_MAX_WL_ ); 101scfx_rep* sub_scfx_rep( const scfx_rep&, const scfx_rep&, 102 int max_wl = SC_DEFAULT_MAX_WL_ ); 103scfx_rep* lsh_scfx_rep( const scfx_rep&, int ); 104scfx_rep* rsh_scfx_rep( const scfx_rep&, int ); 105int cmp_scfx_rep( const scfx_rep&, const scfx_rep& ); 106 107 108const int min_mant = 4; 109 110const int bits_in_int = sizeof(int) * CHAR_BIT; 111const int bits_in_word = sizeof(word) * CHAR_BIT; 112 113 114// ---------------------------------------------------------------------------- 115// CLASS : scfx_index 116// ---------------------------------------------------------------------------- 117 118class scfx_index 119{ 120 121public: 122 123 scfx_index( int wi_, int bi_ ) : m_wi( wi_ ), m_bi( bi_ ) {} 124 125 int wi() const { return m_wi; } 126 int bi() const { return m_bi; } 127 128 void wi( int wi_ ) { m_wi = wi_; } 129 130private: 131 132 int m_wi; 133 int m_bi; 134 135}; 136 137 138// ---------------------------------------------------------------------------- 139// CLASS : scfx_rep 140// 141// Arbitrary-precision fixed-point implementation class. 142// ---------------------------------------------------------------------------- 143 144class scfx_rep 145{ 146 enum state 147 { 148 normal, 149 infinity, 150 not_a_number 151 }; 152 153public: 154 155 // constructors 156 157 scfx_rep(); 158 explicit scfx_rep( int ); 159 explicit scfx_rep( unsigned int ); 160 explicit scfx_rep( long ); 161 explicit scfx_rep( unsigned long ); 162 explicit scfx_rep( double ); 163 explicit scfx_rep( const char* ); 164 explicit scfx_rep( int64 ); 165 explicit scfx_rep( uint64 ); 166 explicit scfx_rep( const sc_signed& ); 167 explicit scfx_rep( const sc_unsigned& ); 168 169 170 // copy constructor 171 172 scfx_rep( const scfx_rep& ); 173 174 175 // destructor 176 177 ~scfx_rep(); 178 179 180 void* operator new( std::size_t ); 181 void operator delete( void*, std::size_t ); 182 183 184 void from_string( const char*, int ); 185 186 double to_double() const; 187 188 const char* to_string( sc_numrep, 189 int, 190 sc_fmt, 191 const scfx_params* = 0 ) const; 192 193 194 // assignment operator 195 196 void operator = ( const scfx_rep& ); 197 198 friend void multiply( scfx_rep&, const scfx_rep&, const scfx_rep&, int ); 199 200 friend scfx_rep* neg_scfx_rep( const scfx_rep& ); 201 friend scfx_rep* mult_scfx_rep( const scfx_rep&, const scfx_rep&, int ); 202 friend scfx_rep* div_scfx_rep( const scfx_rep&, const scfx_rep&, int ); 203 friend scfx_rep* add_scfx_rep( const scfx_rep&, const scfx_rep&, int ); 204 friend scfx_rep* sub_scfx_rep( const scfx_rep&, const scfx_rep&, int ); 205 friend scfx_rep* lsh_scfx_rep( const scfx_rep&, int ); 206 friend scfx_rep* rsh_scfx_rep( const scfx_rep&, int ); 207 208 void lshift( int ); 209 void rshift( int ); 210 211 friend int cmp_scfx_rep( const scfx_rep&, const scfx_rep& ); 212 213 void cast( const scfx_params&, bool&, bool& ); 214 215 bool is_neg() const; 216 bool is_zero() const; 217 bool is_nan() const; 218 bool is_inf() const; 219 bool is_normal() const; 220 221 void set_zero( int = 1 ); 222 void set_nan(); 223 void set_inf( int ); 224 225 bool get_bit( int ) const; 226 bool set( int, const scfx_params& ); 227 bool clear( int, const scfx_params& ); 228 229 bool get_slice( int, int, const scfx_params&, sc_bv_base& ) const; 230 bool set_slice( int, int, const scfx_params&, const sc_bv_base& ); 231 232 void print( ::std::ostream& ) const; 233 void dump( ::std::ostream& ) const; 234 235 void get_type( int&, int&, sc_enc& ) const; 236 237 friend scfx_rep* quantization_scfx_rep( const scfx_rep&, 238 const scfx_params&, 239 bool& ); 240 friend scfx_rep* overflow_scfx_rep( const scfx_rep&, 241 const scfx_params&, 242 bool& ); 243 244 bool rounding_flag() const; 245 246private: 247 248 friend void align( const scfx_rep&, const scfx_rep&, int&, int&, 249 scfx_mant_ref&, scfx_mant_ref& ); 250 friend int compare_msw( const scfx_rep&, const scfx_rep& ); 251 friend int compare_msw_ff( const scfx_rep& lhs, const scfx_rep& rhs ); 252 unsigned int divide_by_ten(); 253 int find_lsw() const; 254 int find_msw() const; 255 void find_sw(); 256 void multiply_by_ten(); 257 void normalize( int ); 258 scfx_mant* resize( int, int ) const; 259 void set_bin( int ); 260 void set_oct( int, int ); 261 void set_hex( int, int ); 262 void shift_left( int ); 263 void shift_right( int ); 264 265 const scfx_index calc_indices( int ) const; 266 267 void o_extend( const scfx_index&, sc_enc ); 268 bool o_bit_at( const scfx_index& ) const; 269 bool o_zero_left( const scfx_index& ) const; 270 bool o_zero_right( const scfx_index& ) const; 271 void o_set_low( const scfx_index&, sc_enc ); 272 void o_set_high( const scfx_index&, const scfx_index&, sc_enc, int = 1 ); 273 void o_set( const scfx_index&, const scfx_index&, sc_enc, bool ); 274 void o_invert( const scfx_index& ); 275 bool q_bit( const scfx_index& ) const; 276 void q_clear( const scfx_index& ); 277 void q_incr( const scfx_index& ); 278 bool q_odd( const scfx_index& ) const; 279 bool q_zero( const scfx_index& ) const; 280 281 void resize_to( int, int = 0 ); 282 int size() const; 283 void toggle_tc(); 284 285 friend void print_dec( scfx_string&, const scfx_rep&, int, sc_fmt ); 286 friend void print_other( scfx_string&, const scfx_rep&, sc_numrep, int, 287 sc_fmt, const scfx_params* ); 288 289 void quantization( const scfx_params&, bool& ); 290 void overflow( const scfx_params&, bool& ); 291 292 friend int compare_abs( const scfx_rep&, const scfx_rep& ); 293 294 void round( int ); 295 296private: 297 298 scfx_mant m_mant; // mantissa (bits of the value). 299 int m_wp; // index of highest order word in value. 300 int m_sign; // sign of value. 301 state m_state; // value state, e.g., normal, inf, etc. 302 int m_msw; // index of most significant non-zero word. 303 int m_lsw; // index of least significant non-zero word. 304 bool m_r_flag; // true if founding occurred. 305 306}; 307 308 309// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII 310 311inline 312void 313scfx_rep::set_zero( int sign ) 314{ 315 m_mant.clear(); 316 m_wp = m_msw = m_lsw = 0; 317 m_sign = sign; 318 m_state = normal; 319} 320 321inline 322void 323scfx_rep::set_nan() 324{ 325 m_mant.resize_to( min_mant ); 326 m_state = not_a_number; 327} 328 329inline 330void 331scfx_rep::set_inf( int sign ) 332{ 333 m_mant.resize_to( min_mant ); 334 m_state = infinity; 335 m_sign = sign; 336} 337 338 339// constructors 340 341inline 342scfx_rep::scfx_rep( const char* s ) 343: m_mant( min_mant ), m_wp( 2 ), m_sign( 1 ), m_state( normal ), 344 m_msw(0), m_lsw(0), m_r_flag( false ) 345{ 346 from_string( s, SC_DEFAULT_CTE_WL_ ); 347} 348 349 350// destructor 351 352inline 353scfx_rep::~scfx_rep() 354{} 355 356 357// assignment operator 358 359inline 360void 361scfx_rep::operator = ( const scfx_rep& f ) 362{ 363 if( &f != this ) 364 { 365 m_mant = f.m_mant; 366 m_wp = f.m_wp; 367 m_sign = f.m_sign; 368 m_state = f.m_state; 369 m_msw = f.m_msw; 370 m_lsw = f.m_lsw; 371 round( SC_DEFAULT_MAX_WL_ ); 372 } 373} 374 375inline 376scfx_rep* 377neg_scfx_rep( const scfx_rep& a ) 378{ 379 scfx_rep& c = *new scfx_rep( a ); 380 c.m_sign = - c.m_sign; 381 return &c; 382} 383 384inline 385scfx_rep* 386mult_scfx_rep( const scfx_rep& a, const scfx_rep& b, int max_wl ) 387{ 388 scfx_rep& c = *new scfx_rep; 389 sc_dt::multiply( c, a, b, max_wl ); 390 return &c; 391} 392 393inline 394scfx_rep* 395lsh_scfx_rep( const scfx_rep& a, int b ) 396{ 397 scfx_rep& c = *new scfx_rep( a ); 398 c.lshift( b ); 399 return &c; 400} 401 402inline 403scfx_rep* 404rsh_scfx_rep( const scfx_rep& a, int b ) 405{ 406 scfx_rep& c = *new scfx_rep( a ); 407 c.rshift( b ); 408 return &c; 409} 410 411inline 412int 413scfx_rep::size() const 414{ 415 return m_mant.size(); 416} 417 418inline 419bool 420scfx_rep::is_neg() const 421{ 422 return ( m_sign == -1 ); 423} 424 425inline 426bool 427scfx_rep::is_zero() const 428{ 429 if( m_state != normal ) 430 return false; 431 432 for( int i = 0; i < size(); i ++ ) 433 { 434 if( m_mant[i] ) 435 return false; 436 } 437 438 return true; 439} 440 441inline 442bool 443scfx_rep::is_nan() const 444{ 445 return ( m_state == not_a_number ); 446} 447 448inline 449bool 450scfx_rep::is_inf() const 451{ 452 return ( m_state == infinity ); 453} 454 455inline 456bool 457scfx_rep::is_normal() const 458{ 459 return ( m_state == normal ); 460} 461 462inline 463scfx_rep* 464quantization_scfx_rep( const scfx_rep& a, 465 const scfx_params& params, 466 bool& q_flag ) 467{ 468 scfx_rep& c = *new scfx_rep( a ); 469 c.quantization( params, q_flag ); 470 return &c; 471} 472 473inline 474scfx_rep* 475overflow_scfx_rep( const scfx_rep& a, 476 const scfx_params& params, 477 bool& o_flag ) 478{ 479 scfx_rep& c = *new scfx_rep( a ); 480 c.overflow( params, o_flag ); 481 return &c; 482} 483 484inline 485bool 486scfx_rep::rounding_flag() const 487{ 488 return m_r_flag; 489} 490 491inline 492void 493scfx_rep::resize_to( int new_size, int restore ) 494{ 495 if( restore == -1 ) 496 { 497 int size_incr = new_size - size(); 498 m_wp += size_incr; 499 m_msw += size_incr; 500 m_lsw += size_incr; 501 } 502 m_mant.resize_to( new_size, restore ); 503} 504 505inline 506const scfx_index 507scfx_rep::calc_indices( int n ) const 508{ 509 int wi = n / bits_in_word + m_wp; 510 int bi = n % bits_in_word; 511 512 if( bi < 0 ) 513 { 514 bi += bits_in_word; 515 -- wi; 516 } 517 518 return scfx_index( wi, bi ); 519} 520 521inline 522void 523scfx_rep::o_extend( const scfx_index& x, sc_enc enc ) 524{ 525 int wi = x.wi(); 526 int bi = x.bi(); 527 528 SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); 529 530 if( enc == SC_US_ || ( m_mant[wi] & ( ((word)1) << bi ) ) == 0 ) 531 { 532 if( bi != bits_in_word - 1 ) 533 m_mant[wi] &= ~( ((word)-1) << ( bi + 1 ) ); 534 for( int i = wi + 1; i < size(); ++ i ) 535 m_mant[i] = 0; 536 m_sign = 1; 537 } 538 else 539 { 540 if( bi != bits_in_word - 1 ) 541 m_mant[wi] |= ( ((word)-1) << ( bi + 1 ) ); 542 for( int i = wi + 1; i < size(); ++ i ) 543 m_mant[i] = static_cast<word>( -1 ); 544 m_sign = -1; 545 } 546} 547 548inline 549bool 550scfx_rep::o_bit_at( const scfx_index& x ) const 551{ 552 int wi = x.wi(); 553 int bi = x.bi(); 554 555 SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); 556 557 return ( m_mant[wi] & ( ((word)1) << bi ) ) != 0; 558} 559 560inline 561bool 562scfx_rep::o_zero_left( const scfx_index& x ) const 563{ 564 int wi = x.wi(); 565 int bi = x.bi(); 566 567 SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); 568 569 bool zero = true; 570 if( bi != bits_in_word - 1 ) 571 zero = ( m_mant[wi] & ( ((word)-1) << ( bi + 1 ) ) ) == 0; 572 for( int i = wi + 1; i < size(); ++ i ) 573 zero = zero && m_mant[i] == 0; 574 575 return zero; 576} 577 578inline 579bool 580scfx_rep::o_zero_right( const scfx_index& x ) const 581{ 582 int wi = x.wi(); 583 int bi = x.bi(); 584 585 SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); 586 587 bool zero = ( m_mant[wi] & ~( ((word)-1) << bi ) ) == 0; 588 for( int i = wi - 1; i >= 0; -- i ) 589 zero = zero && m_mant[i] == 0; 590 591 return zero; 592} 593 594inline 595void 596scfx_rep::o_set_low( const scfx_index& x, sc_enc enc ) 597{ 598 int wi = x.wi(); 599 int bi = x.bi(); 600 601 SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); 602 603 m_mant.clear(); 604 605 if( enc == SC_TC_ ) 606 { 607 m_mant[wi] |= ( ((word)1) << bi ); 608 m_sign = -1; 609 } 610 else 611 m_sign = 1; 612} 613 614inline 615void 616scfx_rep::o_set_high( const scfx_index& x, const scfx_index& x2, 617 sc_enc enc, int sign ) 618{ 619 int wi = x.wi(); 620 int bi = x.bi(); 621 int wi2 = x2.wi(); 622 int bi2 = x2.bi(); 623 624 SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); 625 SC_ASSERT_( wi2 >= 0 && wi2 < size(), "word index out of range" ); 626 627 int i; 628 629 for( i = 0; i < size(); ++ i ) 630 m_mant[i] = static_cast<word>( -1 ); 631 632 m_mant[wi] &= ~( ((word)-1) << bi ); 633 for( i = wi + 1; i < size(); ++ i ) 634 m_mant[i] = 0; 635 636 m_mant[wi2] &= ( ((word)-1) << bi2 ); 637 for( i = wi2 - 1; i >= 0; -- i ) 638 m_mant[i] = 0; 639 640 if( enc == SC_TC_ ) 641 m_sign = sign; 642 else 643 { 644 m_mant[wi] |= ( ((word)1) << bi ); 645 m_sign = 1; 646 } 647} 648 649inline 650void 651scfx_rep::o_set( const scfx_index& x, const scfx_index& x3, 652 sc_enc enc, bool under ) 653{ 654 int wi = x.wi(); 655 int bi = x.bi(); 656 int wi3 = x3.wi(); 657 int bi3 = x3.bi(); 658 659 SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); 660 SC_ASSERT_( wi3 >= 0 && wi3 < size(), "word index out of range" ); 661 662 if( bi3 != bits_in_word - 1 ) 663 { 664 if( under ) 665 m_mant[wi3] &= ~( ((word)-1) << ( bi3 + 1 ) ); 666 else 667 m_mant[wi3] |= ( ((word)-1) << ( bi3 + 1 ) ); 668 } 669 for( int i = wi3 + 1; i < size(); ++ i ) 670 { 671 if( under ) 672 m_mant[i] = 0; 673 else 674 m_mant[i] = static_cast<word>( -1 ); 675 } 676 677 if( enc == SC_TC_ ) 678 { 679 if( under ) 680 m_mant[wi] |= ( ((word)1) << bi ); 681 else 682 m_mant[wi] &= ~( ((word)1) << bi ); 683 } 684} 685 686inline 687void 688scfx_rep::o_invert( const scfx_index& x2 ) 689{ 690 int wi2 = x2.wi(); 691 int bi2 = x2.bi(); 692 693 m_mant[wi2] ^= ( ((word)-1) << bi2 ); 694 for( int i = wi2 + 1; i < size(); ++ i ) 695 m_mant[i] = ~ m_mant[i]; 696} 697 698inline 699bool 700scfx_rep::q_bit( const scfx_index& x ) const 701{ 702 int wi = x.wi(); 703 int bi = x.bi(); 704 705 SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); 706 707 if( bi != 0 ) 708 return ( m_mant[wi] & ( ((word)1) << ( bi - 1 ) ) ) != 0; 709 else if( wi != 0 ) 710 return ( m_mant[wi - 1] & ( ((word)1) << ( bits_in_word - 1 ) ) ) != 0; 711 else 712 return false; 713} 714 715inline 716void 717scfx_rep::q_clear( const scfx_index& x ) 718{ 719 int wi = x.wi(); 720 int bi = x.bi(); 721 722 SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); 723 724 m_mant[wi] &= ( ((word)-1) << bi ); 725 for( int i = wi - 1; i >= 0; -- i ) 726 m_mant[i] = 0; 727} 728 729inline 730void 731scfx_rep::q_incr( const scfx_index& x ) 732{ 733 int wi = x.wi(); 734 int bi = x.bi(); 735 736 SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); 737 738 word old_val = m_mant[wi]; 739 m_mant[wi] += ( ((word)1) << bi ); 740 if( m_mant[wi] <= old_val ) 741 { 742 if( wi + 1 == size() ) 743 resize_to( size() + 1, 1 ); 744 745 for( int i = wi + 1; i < size(); ++ i ) 746 { 747 if( ++ m_mant[i] != 0 ) 748 break; 749 } 750 } 751} 752 753inline 754bool 755scfx_rep::q_odd( const scfx_index& x ) const 756{ 757 int wi = x.wi(); 758 int bi = x.bi(); 759 760 SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); 761 762 return ( m_mant[wi] & ( ((word)1) << bi ) ) != 0; 763} 764 765inline 766bool 767scfx_rep::q_zero( const scfx_index& x ) const 768{ 769 int wi = x.wi(); 770 int bi = x.bi(); 771 772 SC_ASSERT_( wi >= 0 && wi < size(), "word index out of range" ); 773 774 bool zero; 775 776 if( bi != 0 ) 777 { 778 zero = ( m_mant[wi] & ~( ((word)-1) << (bi - 1) ) ) == 0; 779 for( int i = wi - 1; i >= 0; -- i ) 780 zero = zero && m_mant[i] == 0; 781 } 782 else if( wi != 0 ) 783 { 784 zero = ( m_mant[wi - 1] & ~( ((word)-1) << (bits_in_word - 1) ) ) == 0; 785 for( int i = wi - 2; i >= 0; -- i ) 786 zero = zero && m_mant[i] == 0; 787 } 788 else 789 zero = true; 790 791 return zero; 792} 793 794inline 795int 796scfx_rep::find_lsw() const 797{ 798 for( int i = 0; i < size(); i ++ ) 799 { 800 if( m_mant[i] ) 801 return i; 802 } 803 return 0; 804} 805 806inline 807int 808scfx_rep::find_msw() const 809{ 810 for( int i = size() - 1; i >= 0; i -- ) 811 { 812 if( m_mant[i] ) 813 return i; 814 } 815 return 0; 816} 817 818inline 819void 820scfx_rep::find_sw() 821{ 822 m_lsw = find_lsw(); 823 m_msw = find_msw(); 824} 825 826inline 827void 828scfx_rep::toggle_tc() 829{ 830 if( is_neg() ) 831 { 832 complement( m_mant, m_mant, m_mant.size() ); 833 inc( m_mant ); 834 } 835} 836 837} // namespace sc_dt 838 839 840#endif 841 842// Taf! 843