| /***************************************************************************** | |
| 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 ¶ms, 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 ¶ms, 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 |