diff options
Diffstat (limited to 'src/systemc/ext/dt/fx/scfx_rep.hh')
-rw-r--r-- | src/systemc/ext/dt/fx/scfx_rep.hh | 724 |
1 files changed, 724 insertions, 0 deletions
diff --git a/src/systemc/ext/dt/fx/scfx_rep.hh b/src/systemc/ext/dt/fx/scfx_rep.hh new file mode 100644 index 000000000..9465b1afd --- /dev/null +++ b/src/systemc/ext/dt/fx/scfx_rep.hh @@ -0,0 +1,724 @@ +/***************************************************************************** + + Licensed to Accellera Systems Initiative Inc. (Accellera) under one or + more contributor license agreements. See the NOTICE file distributed + with this work for additional information regarding copyright ownership. + Accellera licenses this file to you under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with the + License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + *****************************************************************************/ + +/***************************************************************************** + + scfx_rep.h - + + Original Author: Robert Graulich, Synopsys, Inc. + Martin Janssen, Synopsys, Inc. + + *****************************************************************************/ + +/***************************************************************************** + + MODIFICATION LOG - modifiers, enter your name, affiliation, date and + changes you are making here. + + Name, Affiliation, Date: + Description of Modification: + + *****************************************************************************/ + +// $Log: scfx_rep.h,v $ +// Revision 1.6 2011/08/24 22:05:43 acg +// Torsten Maehne: initialization changes to remove warnings. +// +// Revision 1.5 2011/07/25 10:20:29 acg +// Andy Goodrich: check in aftermath of call to automake. +// +// Revision 1.4 2010/12/07 20:09:08 acg +// Andy Goodrich: Philipp Hartmann's constructor disambiguation fix +// +// Revision 1.3 2010/08/03 15:54:52 acg +// Andy Goodrich: formatting. +// +// Revision 1.2 2010/03/15 18:29:01 acg +// Andy Goodrich: Moved default argument specifications from friend +// declarations to the actual function signatures. +// +// Revision 1.1.1.1 2006/12/15 20:20:04 acg +// SystemC 2.3 +// +// Revision 1.4 2006/03/13 20:24:27 acg +// Andy Goodrich: Addition of function declarations, e.g., neg_scfx_rep(), +// to keep gcc 4.x happy. +// +// Revision 1.3 2006/01/13 18:53:58 acg +// Andy Goodrich: added $Log command so that CVS comments are reproduced in +// the source. +// + +#ifndef __SYSTEMC_EXT_DT_FX_SCFX_REP_HH__ +#define __SYSTEMC_EXT_DT_FX_SCFX_REP_HH__ + +#include <climits> + +#include "scfx_mant.hh" +#include "scfx_params.hh" +#include "scfx_string.hh" + +namespace sc_dt +{ + +// classes defined in this module +class scfx_index; +class scfx_rep; + +// forward class declarations +class sc_bv_base; +class sc_signed; +class sc_unsigned; + +// function declarations +void multiply(scfx_rep &, const scfx_rep &, const scfx_rep &, + int max_wl=SC_DEFAULT_MAX_WL_); +scfx_rep *neg_scfx_rep(const scfx_rep &); +scfx_rep *mult_scfx_rep(const scfx_rep &, const scfx_rep &, + int max_wl=SC_DEFAULT_MAX_WL_); +scfx_rep *div_scfx_rep(const scfx_rep &, const scfx_rep &, + int max_wl=SC_DEFAULT_DIV_WL_); +scfx_rep *add_scfx_rep(const scfx_rep &, const scfx_rep &, + int max_wl=SC_DEFAULT_MAX_WL_); +scfx_rep *sub_scfx_rep(const scfx_rep &, const scfx_rep &, + int max_wl=SC_DEFAULT_MAX_WL_); +scfx_rep *lsh_scfx_rep(const scfx_rep &, int); +scfx_rep *rsh_scfx_rep(const scfx_rep &, int); +int cmp_scfx_rep(const scfx_rep &, const scfx_rep &); + +const int min_mant = 4; + +const int bits_in_int = sizeof(int) * CHAR_BIT; +const int bits_in_word = sizeof(word) * CHAR_BIT; + + +// ---------------------------------------------------------------------------- +// CLASS : scfx_index +// ---------------------------------------------------------------------------- + +class scfx_index +{ + public: + scfx_index(int wi_, int bi_) : m_wi(wi_), m_bi(bi_) {} + + int wi() const { return m_wi; } + int bi() const { return m_bi; } + + void wi(int wi_) { m_wi = wi_; } + + private: + int m_wi; + int m_bi; +}; + + +// ---------------------------------------------------------------------------- +// CLASS : scfx_rep +// +// Arbitrary-precision fixed-point implementation class. +// ---------------------------------------------------------------------------- + +class scfx_rep +{ + enum state + { + normal, + infinity, + not_a_number + }; + + public: + // constructors + scfx_rep(); + explicit scfx_rep(int); + explicit scfx_rep(unsigned int); + explicit scfx_rep(long); + explicit scfx_rep(unsigned long); + explicit scfx_rep(double); + explicit scfx_rep(const char *); + explicit scfx_rep(int64); + explicit scfx_rep(uint64); + explicit scfx_rep(const sc_signed &); + explicit scfx_rep(const sc_unsigned &); + + // copy constructor + scfx_rep(const scfx_rep &); + + // destructor + ~scfx_rep(); + + void *operator new (std::size_t); + void operator delete (void *, std::size_t); + + void from_string(const char *, int); + + double to_double() const; + uint64 to_uint64() const; + + const char *to_string(sc_numrep, int, sc_fmt, + const scfx_params * =0) const; + + // assignment operator + void operator = (const scfx_rep &); + + friend void multiply( scfx_rep&, const scfx_rep&, const scfx_rep&, int ); + + friend scfx_rep *neg_scfx_rep(const scfx_rep &); + friend scfx_rep *mult_scfx_rep(const scfx_rep &, const scfx_rep &, int); + friend scfx_rep *div_scfx_rep(const scfx_rep &, const scfx_rep &, int); + friend scfx_rep *add_scfx_rep(const scfx_rep &, const scfx_rep &, int); + friend scfx_rep *sub_scfx_rep(const scfx_rep &, const scfx_rep &, int); + friend scfx_rep *lsh_scfx_rep(const scfx_rep &, int); + friend scfx_rep *rsh_scfx_rep(const scfx_rep &, int); + + void lshift(int); + void rshift(int); + + friend int cmp_scfx_rep(const scfx_rep &, const scfx_rep &); + + void cast(const scfx_params &, bool &, bool &); + + bool is_neg() const; + bool is_zero() const; + bool is_nan() const; + bool is_inf() const; + bool is_normal() const; + + void set_zero(int=1); + void set_nan(); + void set_inf(int); + + bool get_bit(int) const; + bool set(int, const scfx_params &); + bool clear(int, const scfx_params &); + + bool get_slice(int, int, const scfx_params &, sc_bv_base &) const; + bool set_slice(int, int, const scfx_params &, const sc_bv_base &); + + void print(::std::ostream &) const; + void dump(::std::ostream &) const; + + void get_type(int &, int &, sc_enc &) const; + + friend scfx_rep *quantization_scfx_rep( + const scfx_rep &, const scfx_params &, bool &); + friend scfx_rep *overflow_scfx_rep( + const scfx_rep &, const scfx_params &, bool &); + + bool rounding_flag() const; + + private: + friend void align(const scfx_rep &, const scfx_rep &, int &, int &, + scfx_mant_ref &, scfx_mant_ref &); + friend int compare_msw(const scfx_rep &, const scfx_rep &); + friend int compare_msw_ff(const scfx_rep &lhs, const scfx_rep &rhs); + unsigned int divide_by_ten(); + int find_lsw() const; + int find_msw() const; + void find_sw(); + void multiply_by_ten(); + void normalize(int); + scfx_mant *resize(int, int) const; + void set_bin(int); + void set_oct(int, int); + void set_hex(int, int); + void shift_left(int); + void shift_right(int); + + const scfx_index calc_indices(int) const; + + void o_extend(const scfx_index &, sc_enc); + bool o_bit_at(const scfx_index &) const; + bool o_zero_left(const scfx_index &) const; + bool o_zero_right(const scfx_index &) const; + void o_set_low(const scfx_index &, sc_enc); + void o_set_high(const scfx_index &, const scfx_index &, sc_enc, int=1); + void o_set(const scfx_index &, const scfx_index &, sc_enc, bool); + void o_invert(const scfx_index &); + bool q_bit(const scfx_index &) const; + void q_clear(const scfx_index &); + void q_incr(const scfx_index &); + bool q_odd(const scfx_index &) const; + bool q_zero(const scfx_index &) const; + + void resize_to(int, int=0); + int size() const; + void toggle_tc(); + + friend void print_dec(scfx_string &, const scfx_rep &, int, sc_fmt); + friend void print_other(scfx_string &, const scfx_rep &, sc_numrep, int, + sc_fmt, const scfx_params *); + + void quantization(const scfx_params &, bool &); + void overflow(const scfx_params &, bool &); + + friend int compare_abs(const scfx_rep &, const scfx_rep &); + + void round(int); + + private: + scfx_mant m_mant; // mantissa (bits of the value). + int m_wp; // index of highest order word in value. + int m_sign; // sign of value. + state m_state; // value state, e.g., normal, inf, etc. + int m_msw; // index of most significant non-zero word. + int m_lsw; // index of least significant non-zero word. + bool m_r_flag; // true if rounding occurred. +}; + + +// IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII + +inline void +scfx_rep::set_zero(int sign) +{ + m_mant.clear(); + m_wp = m_msw = m_lsw = 0; + m_sign = sign; + m_state = normal; +} + +inline void +scfx_rep::set_nan() +{ + m_mant.resize_to(min_mant); + m_state = not_a_number; +} + +inline void +scfx_rep::set_inf(int sign) +{ + m_mant.resize_to(min_mant); + m_state = infinity; + m_sign = sign; +} + +// constructors +inline scfx_rep::scfx_rep(const char *s) : + m_mant(min_mant), m_wp(2), m_sign(1), m_state(normal), + m_msw(0), m_lsw(0), m_r_flag(false) +{ + from_string(s, SC_DEFAULT_CTE_WL_); +} + +// destructor +inline scfx_rep::~scfx_rep() {} + +// assignment operator +inline void +scfx_rep::operator = (const scfx_rep &f) +{ + if (&f != this) { + m_mant = f.m_mant; + m_wp = f.m_wp; + m_sign = f.m_sign; + m_state = f.m_state; + m_msw = f.m_msw; + m_lsw = f.m_lsw; + round(SC_DEFAULT_MAX_WL_); + } +} + +inline scfx_rep * +neg_scfx_rep(const scfx_rep &a) +{ + scfx_rep &c = *new scfx_rep(a); + c.m_sign = - c.m_sign; + return &c; +} + +inline scfx_rep * +mult_scfx_rep(const scfx_rep &a, const scfx_rep &b, int max_wl) +{ + scfx_rep &c = *new scfx_rep; + sc_dt::multiply(c, a, b, max_wl); + return &c; +} + +inline scfx_rep * +lsh_scfx_rep(const scfx_rep &a, int b) +{ + scfx_rep &c = *new scfx_rep(a); + c.lshift(b); + return &c; +} + +inline scfx_rep * +rsh_scfx_rep(const scfx_rep &a, int b) +{ + scfx_rep &c = *new scfx_rep(a); + c.rshift(b); + return &c; +} + +inline int scfx_rep::size() const { return m_mant.size(); } + +inline bool scfx_rep::is_neg() const { return (m_sign == -1); } + +inline bool +scfx_rep::is_zero() const +{ + if (m_state != normal) + return false; + + for (int i = 0; i < size(); i++) { + if (m_mant[i]) + return false; + } + + return true; +} + +inline bool scfx_rep::is_nan() const { return (m_state == not_a_number); } + +inline bool scfx_rep::is_inf() const { return (m_state == infinity); } + +inline bool scfx_rep::is_normal() const { return (m_state == normal); } + +inline scfx_rep * +quantization_scfx_rep(const scfx_rep &a, const scfx_params ¶ms, + bool &q_flag) +{ + scfx_rep &c = *new scfx_rep(a); + c.quantization(params, q_flag); + return &c; +} + +inline scfx_rep * +overflow_scfx_rep(const scfx_rep &a, const scfx_params ¶ms, bool &o_flag) +{ + scfx_rep& c = *new scfx_rep(a); + c.overflow(params, o_flag); + return &c; +} + +inline bool scfx_rep::rounding_flag() const { return m_r_flag; } + +inline void +scfx_rep::resize_to(int new_size, int restore) +{ + if (restore == -1) { + int size_incr = new_size - size(); + m_wp += size_incr; + m_msw += size_incr; + m_lsw += size_incr; + } + m_mant.resize_to(new_size, restore); +} + +inline const scfx_index +scfx_rep::calc_indices(int n) const +{ + int wi = n / bits_in_word + m_wp; + int bi = n % bits_in_word; + + if (bi < 0) { + bi += bits_in_word; + -- wi; + } + + return scfx_index(wi, bi); +} + +inline void +scfx_rep::o_extend(const scfx_index &x, sc_enc enc) +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); + + if (enc == SC_US_ || (m_mant[wi] & (((word)1) << bi)) == 0) { + if (bi != bits_in_word - 1) + m_mant[wi] &= ~(((word)-1) << (bi + 1)); + for (int i = wi + 1; i < size(); ++i) + m_mant[i] = 0; + m_sign = 1; + } else { + if (bi != bits_in_word - 1) + m_mant[wi] |= (((word)-1) << (bi + 1)); + for (int i = wi + 1; i < size(); ++i) + m_mant[i] = static_cast<word>(-1); + m_sign = -1; + } +} + +inline bool +scfx_rep::o_bit_at(const scfx_index &x) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); + + return (m_mant[wi] & (((word)1) << bi)) != 0; +} + +inline bool +scfx_rep::o_zero_left(const scfx_index &x) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); + + bool zero = true; + if (bi != bits_in_word - 1) + zero = (m_mant[wi] & (((word)-1) << (bi + 1))) == 0; + for (int i = wi + 1; i < size(); ++i) + zero = zero && m_mant[i] == 0; + + return zero; +} + +inline bool +scfx_rep::o_zero_right(const scfx_index &x) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); + + bool zero = (m_mant[wi] & ~(((word)-1) << bi)) == 0; + for (int i = wi - 1; i >= 0; --i) + zero = zero && m_mant[i] == 0; + + return zero; +} + +inline void +scfx_rep::o_set_low(const scfx_index &x, sc_enc enc) +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); + + m_mant.clear(); + + if (enc == SC_TC_) { + m_mant[wi] |= (((word)1) << bi); + m_sign = -1; + } else { + m_sign = 1; + } +} + +inline void +scfx_rep::o_set_high(const scfx_index &x, const scfx_index &x2, + sc_enc enc, int sign) +{ + int wi = x.wi(); + int bi = x.bi(); + int wi2 = x2.wi(); + int bi2 = x2.bi(); + + SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); + SC_ASSERT_(wi2 >= 0 && wi2 < size(), "word index out of range"); + + int i; + + for (i = 0; i < size(); ++i) + m_mant[i] = static_cast<word>(-1); + + m_mant[wi] &= ~(((word)-1) << bi); + for (i = wi + 1; i < size(); ++i) + m_mant[i] = 0; + + m_mant[wi2] &= (((word)-1) << bi2); + for (i = wi2 - 1; i >= 0; --i) + m_mant[i] = 0; + + if (enc == SC_TC_) { + m_sign = sign; + } else { + m_mant[wi] |= (((word)1) << bi); + m_sign = 1; + } +} + +inline void +scfx_rep::o_set(const scfx_index &x, const scfx_index &x3, sc_enc enc, + bool under) +{ + int wi = x.wi(); + int bi = x.bi(); + int wi3 = x3.wi(); + int bi3 = x3.bi(); + + SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); + SC_ASSERT_(wi3 >= 0 && wi3 < size(), "word index out of range"); + + if (bi3 != bits_in_word - 1) { + if (under) + m_mant[wi3] &= ~(((word)-1) << (bi3 + 1)); + else + m_mant[wi3] |= (((word)-1) << (bi3 + 1)); + } + for (int i = wi3 + 1; i < size(); ++i) { + if (under) + m_mant[i] = 0; + else + m_mant[i] = static_cast<word>(-1); + } + + if (enc == SC_TC_) { + if (under) + m_mant[wi] |= (((word)1) << bi); + else + m_mant[wi] &= ~(((word)1) << bi); + } +} + +inline void +scfx_rep::o_invert(const scfx_index &x2) +{ + int wi2 = x2.wi(); + int bi2 = x2.bi(); + + m_mant[wi2] ^= (((word)-1) << bi2); + for (int i = wi2 + 1; i < size(); ++i) + m_mant[i] = ~ m_mant[i]; +} + +inline bool +scfx_rep::q_bit(const scfx_index &x) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); + + if (bi != 0) + return (m_mant[wi] & (((word)1) << (bi - 1))) != 0; + else if (wi != 0) + return (m_mant[wi - 1] & (((word)1) << (bits_in_word - 1))) != 0; + else + return false; +} + +inline void +scfx_rep::q_clear(const scfx_index &x) +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); + + m_mant[wi] &= (((word)-1) << bi); + for (int i = wi - 1; i >= 0; --i) + m_mant[i] = 0; +} + +inline void +scfx_rep::q_incr(const scfx_index &x) +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); + + word old_val = m_mant[wi]; + m_mant[wi] += (((word)1) << bi); + if (m_mant[wi] <= old_val) { + if (wi + 1 == size()) + resize_to(size() + 1, 1); + + for (int i = wi + 1; i < size(); ++i) { + if (++m_mant[i] != 0) + break; + } + } +} + +inline bool +scfx_rep::q_odd(const scfx_index &x) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); + + return (m_mant[wi] & (((word)1) << bi)) != 0; +} + +inline bool +scfx_rep::q_zero(const scfx_index &x) const +{ + int wi = x.wi(); + int bi = x.bi(); + + SC_ASSERT_(wi >= 0 && wi < size(), "word index out of range"); + + bool zero; + + if (bi != 0) { + zero = (m_mant[wi] & ~(((word)-1) << (bi - 1))) == 0; + for (int i = wi - 1; i >= 0; --i) + zero = zero && m_mant[i] == 0; + } else if (wi != 0) { + zero = (m_mant[wi - 1] & ~( ((word)-1) << (bits_in_word - 1))) == 0; + for (int i = wi - 2; i >= 0; --i) + zero = zero && m_mant[i] == 0; + } else { + zero = true; + } + + return zero; +} + +inline int +scfx_rep::find_lsw() const +{ + for (int i = 0; i < size(); i++) { + if (m_mant[i]) + return i; + } + return 0; +} + +inline int +scfx_rep::find_msw() const +{ + for (int i = size() - 1; i >= 0; i--) { + if (m_mant[i]) + return i; + } + return 0; +} + +inline void +scfx_rep::find_sw() +{ + m_lsw = find_lsw(); + m_msw = find_msw(); +} + +inline void +scfx_rep::toggle_tc() +{ + if (is_neg()) { + complement(m_mant, m_mant, m_mant.size()); + inc(m_mant); + } +} + +} // namespace sc_dt + +#endif // __SYSTEMC_EXT_DT_FX_SCFX_REP_HH__ |