summaryrefslogtreecommitdiff
path: root/src/systemc/dt/fx/sc_fxnum.cc
diff options
context:
space:
mode:
authorGabe Black <gabeblack@google.com>2018-05-24 01:29:36 -0700
committerGabe Black <gabeblack@google.com>2018-08-08 10:09:06 +0000
commit7235d3b5211d0ba8f528d930a4c1e7ad62eec51a (patch)
treec2827b177216f929c502c770ab577f1c73e61318 /src/systemc/dt/fx/sc_fxnum.cc
parent5ee040a534d422ee08918ef49d55620184df7120 (diff)
downloadgem5-7235d3b5211d0ba8f528d930a4c1e7ad62eec51a.tar.xz
systemc: Add the Accellera implementation for the data type classes.
These files have been cleaned up style wise, and some macros have been resolved like they were for the header files. Change-Id: I447e5311961036847e7da0c5a86c0da25a633010 Reviewed-on: https://gem5-review.googlesource.com/10844 Reviewed-by: Gabe Black <gabeblack@google.com> Maintainer: Gabe Black <gabeblack@google.com>
Diffstat (limited to 'src/systemc/dt/fx/sc_fxnum.cc')
-rw-r--r--src/systemc/dt/fx/sc_fxnum.cc867
1 files changed, 867 insertions, 0 deletions
diff --git a/src/systemc/dt/fx/sc_fxnum.cc b/src/systemc/dt/fx/sc_fxnum.cc
new file mode 100644
index 000000000..f47b4d342
--- /dev/null
+++ b/src/systemc/dt/fx/sc_fxnum.cc
@@ -0,0 +1,867 @@
+/*****************************************************************************
+
+ 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.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_fxnum.cpp -
+
+ Original Author: 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: sc_fxnum.cpp,v $
+// Revision 1.3 2011/01/19 18:57:40 acg
+// Andy Goodrich: changes for IEEE_1666_2011.
+//
+// Revision 1.2 2010/12/07 20:09:08 acg
+// Andy Goodrich: Philipp Hartmann's constructor disambiguation fix
+//
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:57 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include <cmath>
+
+#include "systemc/ext/dt/fx/sc_fxnum.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_bitref
+//
+// Proxy class for bit-selection in class sc_fxnum, behaves like sc_bit.
+// ----------------------------------------------------------------------------
+
+bool sc_fxnum_bitref::get() const { return m_num.get_bit(m_idx); }
+void sc_fxnum_bitref::set(bool high) { m_num.set_bit(m_idx, high); }
+
+// print or dump content
+void sc_fxnum_bitref::print(::std::ostream &os) const { os << get(); }
+
+void
+sc_fxnum_bitref::scan(::std::istream &is)
+{
+ bool b;
+ is >> b;
+ *this = b;
+}
+
+void
+sc_fxnum_bitref::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum_bitref" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "num = ";
+ m_num.dump(os);
+ os << "idx = " << m_idx << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_fast_bitref
+//
+// Proxy class for bit-selection in class sc_fxnum_fast, behaves like sc_bit.
+// ----------------------------------------------------------------------------
+
+bool sc_fxnum_fast_bitref::get() const { return m_num.get_bit(m_idx); }
+void sc_fxnum_fast_bitref::set(bool high) { m_num.set_bit(m_idx, high); }
+
+// print or dump content
+void sc_fxnum_fast_bitref::print(::std::ostream &os) const { os << get(); }
+
+void
+sc_fxnum_fast_bitref::scan(::std::istream &is)
+{
+ bool b;
+ is >> b;
+ *this = b;
+}
+
+void
+sc_fxnum_fast_bitref::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum_fast_bitref" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "num = ";
+ m_num.dump(os);
+ os << "idx = " << m_idx << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_subref
+//
+// Proxy class for part-selection in class sc_fxnum,
+// behaves like sc_bv_base.
+// ----------------------------------------------------------------------------
+
+bool
+sc_fxnum_subref::get() const
+{
+ return m_num.get_slice(m_from, m_to, m_bv);
+}
+
+bool
+sc_fxnum_subref::set()
+{
+ return m_num.set_slice(m_from, m_to, m_bv);
+}
+
+// print or dump content
+void
+sc_fxnum_subref::print(::std::ostream &os) const
+{
+ get();
+ m_bv.print(os);
+}
+
+void
+sc_fxnum_subref::scan(::std::istream &is)
+{
+ m_bv.scan(is);
+ set();
+}
+
+void
+sc_fxnum_subref::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum_subref" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "num = ";
+ m_num.dump(os);
+ os << "from = " << m_from << ::std::endl;
+ os << "to = " << m_to << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_fast_subref
+//
+// Proxy class for part-selection in class sc_fxnum_fast,
+// behaves like sc_bv_base.
+// ----------------------------------------------------------------------------
+
+bool
+sc_fxnum_fast_subref::get() const
+{
+ return m_num.get_slice(m_from, m_to, m_bv);
+}
+
+bool
+sc_fxnum_fast_subref::set()
+{
+ return m_num.set_slice(m_from, m_to, m_bv);
+}
+
+// print or dump content
+void
+sc_fxnum_fast_subref::print(::std::ostream &os) const
+{
+ get();
+ m_bv.print(os);
+}
+
+void
+sc_fxnum_fast_subref::scan(::std::istream &is)
+{
+ m_bv.scan(is);
+ set();
+}
+
+void
+sc_fxnum_fast_subref::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum_fast_subref" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "num = ";
+ m_num.dump(os);
+ os << "from = " << m_from << ::std::endl;
+ os << "to = " << m_to << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum
+//
+// Base class for the fixed-point types; arbitrary precision.
+// ----------------------------------------------------------------------------
+
+// explicit conversion to character string
+
+const std::string
+sc_fxnum::to_string() const
+{
+ return std::string(m_rep->to_string(SC_DEC, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_string(sc_numrep numrep) const
+{
+ return std::string(m_rep->to_string(numrep, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_string(sc_numrep numrep, bool w_prefix) const
+{
+ return std::string(m_rep->to_string(numrep, (w_prefix ? 1 : 0),
+ SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_string(sc_fmt fmt) const
+{
+ return std::string(m_rep->to_string(SC_DEC, -1, fmt, &m_params));
+}
+
+const std::string
+sc_fxnum::to_string(sc_numrep numrep, sc_fmt fmt) const
+{
+ return std::string(m_rep->to_string(numrep, -1, fmt, &m_params));
+}
+
+const std::string
+sc_fxnum::to_string(sc_numrep numrep, bool w_prefix, sc_fmt fmt) const
+{
+ return std::string(m_rep->to_string(numrep, (w_prefix ? 1 : 0),
+ fmt, &m_params));
+}
+
+
+const std::string
+sc_fxnum::to_dec() const
+{
+ return std::string(m_rep->to_string(SC_DEC, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_bin() const
+{
+ return std::string(m_rep->to_string(SC_BIN, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_oct() const
+{
+ return std::string(m_rep->to_string(SC_OCT, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_hex() const
+{
+ return std::string(m_rep->to_string(SC_HEX, -1, SC_F, &m_params));
+}
+
+
+// print or dump content
+void
+sc_fxnum::print(::std::ostream &os) const
+{
+ os << m_rep->to_string(SC_DEC, -1, SC_F, &m_params);
+}
+
+void
+sc_fxnum::scan(::std::istream &is)
+{
+ std::string s;
+ is >> s;
+ *this = s.c_str();
+}
+
+void
+sc_fxnum::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "rep = ";
+ m_rep->dump(os);
+ os << "params = ";
+ m_params.dump(os);
+ os << "q_flag = " << m_q_flag << ::std::endl;
+ os << "o_flag = " << m_o_flag << ::std::endl;
+ // TO BE COMPLETED
+ // os << "observer = ";
+ // if (m_observer != 0)
+ // m_observer->dump(os);
+ // else
+ // os << "0" << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+
+sc_fxnum_observer *
+sc_fxnum::lock_observer() const
+{
+ SC_ASSERT_(m_observer != 0, "lock observer failed");
+ sc_fxnum_observer * tmp = m_observer;
+ m_observer = 0;
+ return tmp;
+}
+
+void
+sc_fxnum::unlock_observer(sc_fxnum_observer *observer_) const
+{
+ SC_ASSERT_(observer_ != 0, "unlock observer failed");
+ m_observer = observer_;
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_fast
+//
+// Base class for the fixed-point types; limited precision.
+// ----------------------------------------------------------------------------
+
+static void
+quantization(double &c, const scfx_params &params, bool &q_flag)
+{
+ int fwl = params.wl() - params.iwl();
+ double scale = scfx_pow2(fwl);
+ double val = scale * c;
+ double int_part;
+ double frac_part = modf(val, &int_part);
+
+ q_flag = (frac_part != 0.0);
+
+ if (q_flag) {
+ val = int_part;
+
+ switch (params.q_mode()) {
+ case SC_TRN: // truncation
+ {
+ if (c < 0.0)
+ val -= 1.0;
+ break;
+ }
+ case SC_RND: // rounding to plus infinity
+ {
+ if (frac_part >= 0.5)
+ val += 1.0;
+ else if (frac_part < -0.5)
+ val -= 1.0;
+ break;
+ }
+ case SC_TRN_ZERO: // truncation to zero
+ {
+ break;
+ }
+ case SC_RND_INF: // rounding to infinity
+ {
+ if (frac_part >= 0.5)
+ val += 1.0;
+ else if (frac_part <= -0.5)
+ val -= 1.0;
+ break;
+ }
+ case SC_RND_CONV: // convergent rounding
+ {
+ if (frac_part > 0.5 ||
+ (frac_part == 0.5 && fmod(int_part, 2.0) != 0.0)) {
+ val += 1.0;
+ } else if (frac_part < -0.5 ||
+ (frac_part == -0.5 && fmod(int_part, 2.0) != 0.0)) {
+ val -= 1.0;
+ }
+ break;
+ }
+ case SC_RND_ZERO: // rounding to zero
+ {
+ if (frac_part > 0.5)
+ val += 1.0;
+ else if (frac_part < -0.5)
+ val -= 1.0;
+ break;
+ }
+ case SC_RND_MIN_INF: // rounding to minus infinity
+ {
+ if (frac_part > 0.5)
+ val += 1.0;
+ else if (frac_part <= -0.5)
+ val -= 1.0;
+ break;
+ }
+ default:
+ ;
+ }
+ }
+
+ val /= scale;
+ c = val;
+}
+
+static void
+overflow(double &c, const scfx_params &params, bool &o_flag)
+{
+ int iwl = params.iwl();
+ int fwl = params.wl() - iwl;
+ double full_circle = scfx_pow2(iwl);
+ double resolution = scfx_pow2(-fwl);
+ double low, high;
+ if (params.enc() == SC_TC_) {
+ high = full_circle / 2.0 - resolution;
+ if (params.o_mode() == SC_SAT_SYM)
+ low = - high;
+ else
+ low = - full_circle / 2.0;
+ } else {
+ low = 0.0;
+ high = full_circle - resolution;
+ }
+ double val = c;
+ sc_fxval_fast c2(c);
+
+ bool under = (val < low);
+ bool over = (val > high);
+
+ o_flag = (under || over);
+
+ if (o_flag) {
+ switch (params.o_mode()) {
+ case SC_WRAP: // wrap-around
+ {
+ int n_bits = params.n_bits();
+
+ if (n_bits == 0) {
+ // wrap-around all 'wl' bits
+ val -= floor(val / full_circle) * full_circle;
+ if (val > high)
+ val -= full_circle;
+ } else if (n_bits < params.wl()) {
+ double X = scfx_pow2(iwl - n_bits);
+
+ // wrap-around least significant 'wl - n_bits' bits
+ val -= floor(val / X) * X;
+ if (val > (X - resolution))
+ val -= X;
+
+ // saturate most significant 'n_bits' bits
+ if (under) {
+ val += low;
+ } else {
+ if (params.enc() == SC_TC_)
+ val += full_circle / 2.0 - X;
+ else
+ val += full_circle - X;
+ }
+ } else {
+ // saturate all 'wl' bits
+ if (under)
+ val = low;
+ else
+ val = high;
+ }
+ break;
+ }
+ case SC_SAT: // saturation
+ case SC_SAT_SYM: // symmetrical saturation
+ {
+ if (under)
+ val = low;
+ else
+ val = high;
+ break;
+ }
+ case SC_SAT_ZERO: // saturation to zero
+ {
+ val = 0.0;
+ break;
+ }
+ case SC_WRAP_SM: // sign magnitude wrap-around
+ {
+ SC_ERROR_IF_(params.enc() == SC_US_,
+ "SC_WRAP_SM not defined for unsigned numbers");
+
+ int n_bits = params.n_bits();
+
+ if (n_bits == 0) {
+ // invert conditionally
+ if (c2.get_bit(iwl) != c2.get_bit(iwl - 1))
+ val = -val - resolution;
+
+ // wrap-around all 'wl' bits
+ val -= floor(val / full_circle) * full_circle;
+ if (val > high)
+ val -= full_circle;
+ } else if (n_bits == 1) {
+ // invert conditionally
+ if (c2.is_neg() != c2.get_bit(iwl - 1))
+ val = -val - resolution;
+
+ // wrap-around all 'wl' bits
+ val -= floor(val / full_circle) * full_circle;
+ if (val > high)
+ val -= full_circle;
+ } else if (n_bits < params.wl()) {
+ // invert conditionally
+ if (c2.is_neg() == c2.get_bit(iwl - n_bits))
+ val = -val - resolution;
+
+ double X = scfx_pow2(iwl - n_bits);
+
+ // wrap-around least significant 'wl - n_bits' bits
+ val -= floor(val / X) * X;
+ if (val > (X - resolution))
+ val -= X;
+
+ // saturate most significant 'n_bits' bits
+ if (under)
+ val += low;
+ else
+ val += full_circle / 2.0 - X;
+ } else {
+ // saturate all 'wl' bits
+ if (under)
+ val = low;
+ else
+ val = high;
+ }
+ break;
+ }
+ default:
+ ;
+ }
+
+ c = val;
+ }
+}
+
+
+void
+sc_fxnum_fast::cast()
+{
+ scfx_ieee_double id(m_val);
+ SC_ERROR_IF_(id.is_nan() || id.is_inf(), "invalid fixed-point value");
+
+ if (m_params.cast_switch() == SC_ON) {
+ m_q_flag = false;
+ m_o_flag = false;
+
+ // check for special cases
+
+ if (id.is_zero()) {
+ if (id.negative() != 0)
+ m_val = -m_val;
+ return;
+ }
+
+ // perform casting
+ sc_dt::quantization(m_val, m_params, m_q_flag);
+ sc_dt::overflow(m_val, m_params, m_o_flag);
+
+ // check for special case: -0
+ id = m_val;
+ if (id.is_zero() && id.negative() != 0) {
+ m_val = -m_val;
+ }
+
+ // check for special case: NaN of Inf
+ if (id.is_nan() || id.is_inf()) {
+ m_val = 0.0;
+ }
+ }
+}
+
+
+// defined in sc_fxval.cpp;
+extern const char* to_string(const scfx_ieee_double &, sc_numrep, int, sc_fmt,
+ const scfx_params * =0);
+
+
+// explicit conversion to character string
+
+const std::string
+sc_fxnum_fast::to_string() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_DEC, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_string(sc_numrep numrep) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_string(sc_numrep numrep, bool w_prefix) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, (w_prefix ? 1 : 0),
+ SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_string(sc_fmt fmt) const
+{
+ return std::string(sc_dt::to_string(m_val, SC_DEC, -1, fmt, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_string(sc_numrep numrep, sc_fmt fmt) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, -1, fmt, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_string(sc_numrep numrep, bool w_prefix, sc_fmt fmt) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, (w_prefix ? 1 : 0),
+ fmt, &m_params));
+}
+
+
+const std::string
+sc_fxnum_fast::to_dec() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_DEC, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_bin() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_BIN, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_oct() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_OCT, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_hex() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_HEX, -1, SC_F, &m_params));
+}
+
+// print or dump content
+void
+sc_fxnum_fast::print(::std::ostream &os) const
+{
+ os << sc_dt::to_string(m_val, SC_DEC, -1, SC_F, &m_params);
+}
+
+void
+sc_fxnum_fast::scan(::std::istream &is)
+{
+ std::string s;
+ is >> s;
+ *this = s.c_str();
+}
+
+void
+sc_fxnum_fast::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum_fast" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "val = " << m_val << ::std::endl;
+ os << "params = ";
+ m_params.dump(os);
+ os << "q_flag = " << m_q_flag << ::std::endl;
+ os << "o_flag = " << m_o_flag << ::std::endl;
+ // TO BE COMPLETED
+ // os << "observer = ";
+ // if (m_observer != 0)
+ // m_observer->dump(os);
+ // else
+ // os << "0" << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+// internal use only;
+bool
+sc_fxnum_fast::get_bit(int i) const
+{
+ scfx_ieee_double id(m_val);
+ if (id.is_zero() || id.is_nan() || id.is_inf())
+ return false;
+
+ // convert to two's complement
+ unsigned int m0 = id.mantissa0();
+ unsigned int m1 = id.mantissa1();
+
+ if (id.is_normal())
+ m0 += 1U << 20;
+
+ if (id.negative() != 0) {
+ m0 = ~ m0;
+ m1 = ~ m1;
+ unsigned int tmp = m1;
+ m1 += 1U;
+ if (m1 <= tmp)
+ m0 += 1U;
+ }
+
+ // get the right bit
+ int j = i - id.exponent();
+ if ((j += 20) >= 32)
+ return ((m0 & 1U << 31) != 0);
+ else if (j >= 0)
+ return ((m0 & 1U << j) != 0);
+ else if ((j += 32) >= 0)
+ return ((m1 & 1U << j) != 0);
+ else
+ return false;
+}
+
+
+bool
+sc_fxnum_fast::set_bit(int i, bool high)
+{
+ scfx_ieee_double id(m_val);
+ if (id.is_nan() || id.is_inf())
+ return false;
+
+ if (high) {
+ if (get_bit(i))
+ return true;
+
+ if (m_params.enc() == SC_TC_ && i == m_params.iwl() - 1)
+ m_val -= scfx_pow2(i);
+ else
+ m_val += scfx_pow2(i);
+ } else {
+ if (!get_bit(i))
+ return true;
+
+ if (m_params.enc() == SC_TC_ && i == m_params.iwl() - 1)
+ m_val += scfx_pow2(i);
+ else
+ m_val -= scfx_pow2(i);
+ }
+
+ return true;
+}
+
+
+bool
+sc_fxnum_fast::get_slice(int i, int j, sc_bv_base &bv) const
+{
+ scfx_ieee_double id(m_val);
+ if (id.is_nan() || id.is_inf())
+ return false;
+
+ // convert to two's complement
+ unsigned int m0 = id.mantissa0();
+ unsigned int m1 = id.mantissa1();
+
+ if (id.is_normal())
+ m0 += 1U << 20;
+
+ if (id.negative() != 0) {
+ m0 = ~ m0;
+ m1 = ~ m1;
+ unsigned int tmp = m1;
+ m1 += 1U;
+ if (m1 <= tmp)
+ m0 += 1U;
+ }
+
+ // get the bits
+ int l = j;
+ for (int k = 0; k < bv.length(); ++ k) {
+ bool b = false;
+
+ int n = l - id.exponent();
+ if ((n += 20) >= 32)
+ b = ((m0 & 1U << 31) != 0);
+ else if (n >= 0)
+ b = ((m0 & 1U << n) != 0);
+ else if ((n += 32) >= 0)
+ b = ((m1 & 1U << n) != 0);
+
+ bv[k] = b;
+
+ if (i >= j)
+ ++l;
+ else
+ --l;
+ }
+
+ return true;
+}
+
+bool
+sc_fxnum_fast::set_slice(int i, int j, const sc_bv_base &bv)
+{
+ scfx_ieee_double id(m_val);
+ if (id.is_nan() || id.is_inf())
+ return false;
+
+ // set the bits
+ int l = j;
+ for (int k = 0; k < bv.length(); ++k) {
+ if (bv[k].to_bool()) {
+ if (!get_bit(l)) {
+ if (m_params.enc() == SC_TC_ && l == m_params.iwl() - 1)
+ m_val -= scfx_pow2(l);
+ else
+ m_val += scfx_pow2(l);
+ }
+ } else {
+ if (get_bit(l)) {
+ if (m_params.enc() == SC_TC_ && l == m_params.iwl() - 1)
+ m_val += scfx_pow2(l);
+ else
+ m_val -= scfx_pow2(l);
+ }
+ }
+
+ if (i >= j)
+ ++l;
+ else
+ --l;
+ }
+
+ return true;
+}
+
+sc_fxnum_fast_observer *
+sc_fxnum_fast::lock_observer() const
+{
+ SC_ASSERT_(m_observer != 0, "lock observer failed");
+ sc_fxnum_fast_observer *tmp = m_observer;
+ m_observer = 0;
+ return tmp;
+}
+
+void
+sc_fxnum_fast::unlock_observer(sc_fxnum_fast_observer *observer_) const
+{
+ SC_ASSERT_(observer_ != 0, "unlock observer failed");
+ m_observer = observer_;
+}
+
+} // namespace sc_dt