summaryrefslogtreecommitdiff
path: root/src/systemc/ext/dt/fx/scfx_rep.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemc/ext/dt/fx/scfx_rep.hh')
-rw-r--r--src/systemc/ext/dt/fx/scfx_rep.hh724
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 &params,
+ 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 &params, 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__