summaryrefslogtreecommitdiff
path: root/src/systemc/dt/fx
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
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')
-rw-r--r--src/systemc/dt/fx/SConscript41
-rw-r--r--src/systemc/dt/fx/sc_fxcast_switch.cc86
-rw-r--r--src/systemc/dt/fx/sc_fxdefs.cc166
-rw-r--r--src/systemc/dt/fx/sc_fxnum.cc867
-rw-r--r--src/systemc/dt/fx/sc_fxnum_observer.cc70
-rw-r--r--src/systemc/dt/fx/sc_fxtype_params.cc97
-rw-r--r--src/systemc/dt/fx/sc_fxval.cc810
-rw-r--r--src/systemc/dt/fx/sc_fxval_observer.cc72
-rw-r--r--src/systemc/dt/fx/scfx_mant.cc117
-rw-r--r--src/systemc/dt/fx/scfx_pow10.cc129
-rw-r--r--src/systemc/dt/fx/scfx_rep.cc2651
-rw-r--r--src/systemc/dt/fx/scfx_utils.cc162
12 files changed, 5268 insertions, 0 deletions
diff --git a/src/systemc/dt/fx/SConscript b/src/systemc/dt/fx/SConscript
new file mode 100644
index 000000000..698496cf4
--- /dev/null
+++ b/src/systemc/dt/fx/SConscript
@@ -0,0 +1,41 @@
+# Copyright 2018 Google, Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Gabe Black
+
+Import('*')
+
+if env['USE_SYSTEMC']:
+ Source('sc_fxcast_switch.cc')
+ Source('sc_fxdefs.cc')
+ Source('scfx_mant.cc')
+ Source('sc_fxnum.cc')
+ Source('sc_fxnum_observer.cc')
+ Source('scfx_pow10.cc')
+ Source('scfx_rep.cc')
+ Source('sc_fxtype_params.cc')
+ Source('scfx_utils.cc')
+ Source('sc_fxval.cc')
+ Source('sc_fxval_observer.cc')
diff --git a/src/systemc/dt/fx/sc_fxcast_switch.cc b/src/systemc/dt/fx/sc_fxcast_switch.cc
new file mode 100644
index 000000000..9aabe14ae
--- /dev/null
+++ b/src/systemc/dt/fx/sc_fxcast_switch.cc
@@ -0,0 +1,86 @@
+/*****************************************************************************
+
+ 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_fxcast_switch.cpp -
+
+ Original Author: Martin Janssen, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date: Gene Bushuyev, Synopsys, Inc.
+ Description of Modification: - fix explicit instantiation syntax.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_fxcast_switch.cpp,v $
+// 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 "systemc/ext/dt/fx/sc_fxcast_switch.hh"
+
+namespace sc_dt
+{
+
+template class sc_global<sc_fxcast_switch>;
+template class sc_context<sc_fxcast_switch>;
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxcast_switch
+//
+// Fixed-point cast switch class.
+// ----------------------------------------------------------------------------
+
+const std::string
+sc_fxcast_switch::to_string() const
+{
+ return sc_dt::to_string(m_sw);
+}
+
+void
+sc_fxcast_switch::print(::std::ostream &os) const
+{
+ os << sc_dt::to_string(m_sw);
+}
+
+void
+sc_fxcast_switch::dump(::std::ostream &os) const
+{
+ os << "sc_fxcast_switch" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "sw = " << sc_dt::to_string(m_sw) << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+} // namespace sc_dt
diff --git a/src/systemc/dt/fx/sc_fxdefs.cc b/src/systemc/dt/fx/sc_fxdefs.cc
new file mode 100644
index 000000000..4a9e7458f
--- /dev/null
+++ b/src/systemc/dt/fx/sc_fxdefs.cc
@@ -0,0 +1,166 @@
+/*****************************************************************************
+
+ 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_fxdefs.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_fxdefs.cpp,v $
+// 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 "systemc/ext/dt/fx/sc_fxdefs.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// ENUM : sc_enc
+//
+// Enumeration of sign encodings.
+// ----------------------------------------------------------------------------
+
+const std::string
+to_string(sc_enc enc)
+{
+ switch (enc) {
+ case SC_TC_:
+ return std::string("SC_TC_");
+ case SC_US_:
+ return std::string("SC_US_");
+ default:
+ return std::string("unknown");
+ }
+}
+
+// ----------------------------------------------------------------------------
+// ENUM : sc_q_mode
+//
+// Enumeration of quantization modes.
+// ----------------------------------------------------------------------------
+
+const std::string
+to_string(sc_q_mode q_mode)
+{
+ switch (q_mode) {
+ case SC_RND:
+ return std::string("SC_RND");
+ case SC_RND_ZERO:
+ return std::string("SC_RND_ZERO");
+ case SC_RND_MIN_INF:
+ return std::string("SC_RND_MIN_INF");
+ case SC_RND_INF:
+ return std::string("SC_RND_INF");
+ case SC_RND_CONV:
+ return std::string("SC_RND_CONV");
+ case SC_TRN:
+ return std::string("SC_TRN");
+ case SC_TRN_ZERO:
+ return std::string("SC_TRN_ZERO");
+ default:
+ return std::string("unknown");
+ }
+}
+
+// ----------------------------------------------------------------------------
+// ENUM : sc_o_mode
+//
+// Enumeration of overflow modes.
+// ----------------------------------------------------------------------------
+
+const std::string
+to_string(sc_o_mode o_mode)
+{
+ switch (o_mode) {
+ case SC_SAT:
+ return std::string("SC_SAT");
+ case SC_SAT_ZERO:
+ return std::string("SC_SAT_ZERO");
+ case SC_SAT_SYM:
+ return std::string("SC_SAT_SYM");
+ case SC_WRAP:
+ return std::string("SC_WRAP");
+ case SC_WRAP_SM:
+ return std::string("SC_WRAP_SM");
+ default:
+ return std::string("unknown");
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// ENUM : sc_switch
+//
+// Enumeration of switch states.
+// ----------------------------------------------------------------------------
+
+const std::string
+to_string(sc_switch sw)
+{
+ switch (sw) {
+ case SC_OFF:
+ return std::string("SC_OFF");
+ case SC_ON:
+ return std::string("SC_ON");
+ default:
+ return std::string("unknown");
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// ENUM : sc_fmt
+//
+// Enumeration of formats for character string conversion.
+// ----------------------------------------------------------------------------
+
+const std::string
+to_string(sc_fmt fmt)
+{
+ switch (fmt) {
+ case SC_F:
+ return std::string("SC_F");
+ case SC_E:
+ return std::string("SC_E");
+ default:
+ return std::string("unknown");
+ }
+}
+
+} // namespace sc_dt
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
diff --git a/src/systemc/dt/fx/sc_fxnum_observer.cc b/src/systemc/dt/fx/sc_fxnum_observer.cc
new file mode 100644
index 000000000..1ee3c9b8b
--- /dev/null
+++ b/src/systemc/dt/fx/sc_fxnum_observer.cc
@@ -0,0 +1,70 @@
+/*****************************************************************************
+
+ 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_observer.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_observer.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:58 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include "systemc/ext/dt/fx/sc_fxnum_observer.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_observer
+//
+// Abstract base class for fixed-point types observers; arbitrary precision.
+// ----------------------------------------------------------------------------
+
+sc_fxnum_observer *(* sc_fxnum_observer::default_observer) () = 0;
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_fast_observer
+//
+// Abstract base class for fixed-point types observers; limited precision.
+// ----------------------------------------------------------------------------
+
+sc_fxnum_fast_observer *(* sc_fxnum_fast_observer::default_observer) () = 0;
+
+} // namespace sc_dt
diff --git a/src/systemc/dt/fx/sc_fxtype_params.cc b/src/systemc/dt/fx/sc_fxtype_params.cc
new file mode 100644
index 000000000..54af8a7ee
--- /dev/null
+++ b/src/systemc/dt/fx/sc_fxtype_params.cc
@@ -0,0 +1,97 @@
+/*****************************************************************************
+
+ 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_fxtype_params.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_fxtype_params.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:58 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include <sstream>
+
+#include "systemc/ext/dt/fx/sc_fxtype_params.hh"
+
+namespace sc_dt
+{
+
+template class sc_global<sc_fxtype_params>;
+template class sc_context<sc_fxtype_params>;
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxtype_params
+//
+// Fixed-point type parameters class.
+// ----------------------------------------------------------------------------
+
+const std::string
+sc_fxtype_params::to_string() const
+{
+ std::stringstream ss;
+ print(ss);
+ return ss.str();
+}
+
+void
+sc_fxtype_params::print(::std::ostream &os) const
+{
+ os << "("
+ << m_wl << ","
+ << m_iwl << ","
+ << m_q_mode << ","
+ << m_o_mode << ","
+ << m_n_bits
+ << ")";
+}
+
+void
+sc_fxtype_params::dump(::std::ostream &os) const
+{
+ os << "sc_fxtype_params" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "wl = " << m_wl << ::std::endl;
+ os << "iwl = " << m_iwl << ::std::endl;
+ os << "q_mode = " << m_q_mode << ::std::endl;
+ os << "o_mode = " << m_o_mode << ::std::endl;
+ os << "n_bits = " << m_n_bits << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+} // namespace sc_dt
diff --git a/src/systemc/dt/fx/sc_fxval.cc b/src/systemc/dt/fx/sc_fxval.cc
new file mode 100644
index 000000000..45d7d5735
--- /dev/null
+++ b/src/systemc/dt/fx/sc_fxval.cc
@@ -0,0 +1,810 @@
+/*****************************************************************************
+
+ 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_fxval.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_fxval.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:58 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include <cctype>
+#include <cfloat>
+#include <cmath>
+#include <cstdlib>
+
+#include "systemc/ext/dt/fx/sc_fxval.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxval
+//
+// Fixed-point value type; arbitrary precision.
+// ----------------------------------------------------------------------------
+
+// explicit conversion to character string
+
+const std::string
+sc_fxval::to_string() const
+{
+ return std::string(m_rep->to_string(SC_DEC, -1, SC_E));
+}
+
+const std::string
+sc_fxval::to_string(sc_numrep numrep) const
+{
+ return std::string(m_rep->to_string(numrep, -1, SC_E));
+}
+
+const std::string
+sc_fxval::to_string(sc_numrep numrep, bool w_prefix) const
+{
+ return std::string(m_rep->to_string(numrep, (w_prefix ? 1 : 0), SC_E));
+}
+
+const std::string
+sc_fxval::to_string(sc_fmt fmt) const
+{
+ return std::string(m_rep->to_string(SC_DEC, -1, fmt));
+}
+
+const std::string
+sc_fxval::to_string(sc_numrep numrep, sc_fmt fmt) const
+{
+ return std::string(m_rep->to_string(numrep, -1, fmt));
+}
+
+const std::string
+sc_fxval::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));
+}
+
+
+const std::string
+sc_fxval::to_dec() const
+{
+ return std::string(m_rep->to_string(SC_DEC, -1, SC_E));
+}
+
+const std::string
+sc_fxval::to_bin() const
+{
+ return std::string(m_rep->to_string(SC_BIN, -1, SC_E));
+}
+
+const std::string
+sc_fxval::to_oct() const
+{
+ return std::string(m_rep->to_string(SC_OCT, -1, SC_E));
+}
+
+const std::string
+sc_fxval::to_hex() const
+{
+ return std::string(m_rep->to_string(SC_HEX, -1, SC_E));
+}
+
+
+// print or dump content
+
+void sc_fxval::print(::std::ostream &os) const { m_rep->print(os); }
+
+void
+sc_fxval::scan(::std::istream &is)
+{
+ std::string s;
+ is >> s;
+ *this = s.c_str();
+}
+
+void
+sc_fxval::dump(::std::ostream &os) const
+{
+ os << "sc_fxval" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "rep = ";
+ m_rep->dump(os);
+ // TO BE COMPLETED
+ // os << "r_flag = " << m_r_flag << ::std::endl;
+ // os << "observer = ";
+ // if (m_observer != 0)
+ // m_observer->dump(os);
+ // else
+ // os << "0" << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+// protected methods and friend functions
+sc_fxval_observer *
+sc_fxval::lock_observer() const
+{
+ SC_ASSERT_(m_observer != 0, "lock observer failed");
+ sc_fxval_observer *tmp = m_observer;
+ m_observer = 0;
+ return tmp;
+}
+
+void
+sc_fxval::unlock_observer(sc_fxval_observer *observer_) const
+{
+ SC_ASSERT_(observer_ != 0, "unlock observer failed");
+ m_observer = observer_;
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxval_fast
+//
+// Fixed-point value types; limited precision.
+// ----------------------------------------------------------------------------
+
+static void
+print_dec(scfx_string &s, scfx_ieee_double id, int w_prefix, sc_fmt fmt)
+{
+ if (id.negative() != 0) {
+ id.negative(0);
+ s += '-';
+ }
+
+ if (w_prefix == 1) {
+ scfx_print_prefix(s, SC_DEC);
+ }
+
+ if (id.is_zero()) {
+ s += '0';
+ return;
+ }
+
+ // split 'id' into its integer and fractional part
+ double int_part;
+ double frac_part = std::modf(static_cast<double>(id), &int_part);
+
+ int i;
+
+ // print integer part
+ int int_digits = 0;
+ int int_zeros = 0;
+
+ if (int_part != 0.0) {
+ int_digits = (int)std::ceil(std::log10(int_part + 1.0));
+
+ int len = s.length();
+ s.append(int_digits);
+
+ bool zero_digits = (frac_part == 0.0 && fmt != SC_F);
+
+ for (i = int_digits + len - 1; i >= len; i--) {
+ unsigned int remainder = (unsigned int)std::fmod(int_part, 10.0);
+ s[i] = static_cast<char>('0' + remainder);
+
+ if (zero_digits) {
+ if (remainder == 0)
+ int_zeros++;
+ else
+ zero_digits = false;
+ }
+
+ int_part /= 10.0;
+ }
+
+ // discard trailing zeros from int_part
+ s.discard(int_zeros);
+
+ if (s[len] == '0') {
+ // int_digits was overestimated by one
+ s.remove(len);
+ --int_digits;
+ }
+ }
+
+ // print fractional part
+ int frac_digits = 0;
+ int frac_zeros = 0;
+
+ if (frac_part != 0.0) {
+ s += '.';
+
+ bool zero_digits = (int_digits == 0 && fmt != SC_F);
+
+ frac_zeros = (int)std::floor(-std::log10(frac_part + DBL_EPSILON));
+
+ frac_part *= std::pow(10.0, frac_zeros);
+
+ frac_digits = frac_zeros;
+ if (!zero_digits) {
+ for (i = 0; i < frac_zeros; i++)
+ s += '0';
+ frac_zeros = 0;
+ }
+
+ while (frac_part != 0.0) {
+ frac_part *= 10.0;
+ int n = static_cast<int>(frac_part);
+
+ if (zero_digits) {
+ if (n == 0)
+ frac_zeros++;
+ else
+ zero_digits = false;
+ }
+
+ if (!zero_digits)
+ s += static_cast<char>('0' + n);
+
+ frac_part -= n;
+ frac_digits++;
+ }
+ }
+
+ // print exponent
+ if (fmt != SC_F) {
+ if (frac_digits == 0)
+ scfx_print_exp(s, int_zeros);
+ else if (int_digits == 0)
+ scfx_print_exp(s, -frac_zeros);
+ }
+}
+
+static void
+print_other(scfx_string &s, const scfx_ieee_double &id, sc_numrep numrep,
+ int w_prefix, sc_fmt fmt, const scfx_params *params)
+{
+ scfx_ieee_double id2 = id;
+
+ sc_numrep numrep2 = numrep;
+
+ bool numrep_is_sm = (numrep == SC_BIN_SM ||
+ numrep == SC_OCT_SM ||
+ numrep == SC_HEX_SM);
+
+ if (numrep_is_sm) {
+ if (id2.negative() != 0) {
+ s += '-';
+ id2.negative(0);
+ }
+ switch (numrep) {
+ case SC_BIN_SM:
+ numrep2 = SC_BIN_US;
+ break;
+ case SC_OCT_SM:
+ numrep2 = SC_OCT_US;
+ break;
+ case SC_HEX_SM:
+ numrep2 = SC_HEX_US;
+ break;
+ default:
+ ;
+ }
+ }
+
+ if (w_prefix != 0) {
+ scfx_print_prefix(s, numrep);
+ }
+
+ numrep = numrep2;
+
+ sc_fxval_fast a(id2);
+
+ int msb, lsb;
+
+ if (params != 0) {
+ msb = params->iwl() - 1;
+ lsb = params->iwl() - params->wl();
+
+ if (params->enc() == SC_TC_ &&
+ (numrep == SC_BIN_US ||
+ numrep == SC_OCT_US ||
+ numrep == SC_HEX_US) &&
+ !numrep_is_sm &&
+ params->wl() > 1) {
+ --msb;
+ } else if (params->enc() == SC_US_ &&
+ (numrep == SC_BIN ||
+ numrep == SC_OCT ||
+ numrep == SC_HEX ||
+ numrep == SC_CSD)) {
+ ++msb;
+ }
+ } else {
+ if (a.is_zero()) {
+ msb = 0;
+ lsb = 0;
+ } else {
+ msb = id2.exponent() + 1;
+ while (a.get_bit(msb) == a.get_bit(msb - 1))
+ --msb;
+
+ if (numrep == SC_BIN_US ||
+ numrep == SC_OCT_US ||
+ numrep == SC_HEX_US) {
+ --msb;
+ }
+
+ lsb = id2.exponent() - 52;
+ while (!a.get_bit(lsb))
+ ++lsb;
+ }
+ }
+
+ int step;
+
+ switch (numrep) {
+ case SC_BIN:
+ case SC_BIN_US:
+ case SC_CSD:
+ step = 1;
+ break;
+ case SC_OCT:
+ case SC_OCT_US:
+ step = 3;
+ break;
+ case SC_HEX:
+ case SC_HEX_US:
+ step = 4;
+ break;
+ default:
+ SC_REPORT_FATAL("assertion failed", "unexpected sc_numrep");
+ sc_core::sc_abort();
+ }
+
+ msb = (int)std::ceil(double(msb + 1) / step) * step - 1;
+
+ lsb = (int)std::floor(double(lsb) / step) * step;
+
+ if (msb < 0) {
+ s += '.';
+ if (fmt == SC_F) {
+ int sign = (id2.negative() != 0) ? (1 << step) - 1 : 0;
+ for (int i = (msb + 1) / step; i < 0; i++) {
+ if (sign < 10)
+ s += static_cast<char>(sign + '0');
+ else
+ s += static_cast<char>(sign + 'a' - 10);
+ }
+ }
+ }
+
+ int i = msb;
+ while (i >= lsb) {
+ int value = 0;
+ for (int j = step - 1; j >= 0; --j) {
+ value += static_cast<int>(a.get_bit(i)) << j;
+ --i;
+ }
+ if (value < 10)
+ s += static_cast<char>(value + '0');
+ else
+ s += static_cast<char>(value + 'a' - 10);
+ if (i == -1)
+ s += '.';
+ }
+
+ if (lsb > 0 && fmt == SC_F) {
+ for (int i = lsb / step; i > 0; i--)
+ s += '0';
+ }
+
+ if (s[s.length() - 1] == '.')
+ s.discard(1);
+
+ if (fmt != SC_F) {
+ if (msb < 0)
+ scfx_print_exp(s, (msb + 1) / step);
+ else if (lsb > 0)
+ scfx_print_exp(s, lsb / step);
+ }
+
+ if (numrep == SC_CSD)
+ scfx_tc2csd(s, w_prefix);
+}
+
+const char *
+to_string(const scfx_ieee_double &id, sc_numrep numrep, int w_prefix,
+ sc_fmt fmt, const scfx_params *params=0)
+{
+ static scfx_string s;
+
+ s.clear();
+
+ if (id.is_nan()) {
+ scfx_print_nan(s);
+ } else if (id.is_inf()) {
+ scfx_print_inf(s, static_cast<bool>(id.negative()));
+ } else if (id.negative() && !id.is_zero() &&
+ (numrep == SC_BIN_US ||
+ numrep == SC_OCT_US ||
+ numrep == SC_HEX_US)) {
+ s += "negative";
+ } else if (numrep == SC_DEC) {
+ sc_dt::print_dec(s, id, w_prefix, fmt);
+ } else {
+ sc_dt::print_other(s, id, numrep, w_prefix, fmt, params);
+ }
+
+ return s;
+}
+
+
+// explicit conversion to character string
+const std::string
+sc_fxval_fast::to_string() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_DEC, -1, SC_E));
+}
+
+const std::string
+sc_fxval_fast::to_string(sc_numrep numrep) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, -1, SC_E));
+}
+
+const std::string
+sc_fxval_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_E));
+}
+
+const std::string
+sc_fxval_fast::to_string(sc_fmt fmt) const
+{
+ return std::string(sc_dt::to_string(m_val, SC_DEC, -1, fmt));
+}
+
+const std::string
+sc_fxval_fast::to_string(sc_numrep numrep, sc_fmt fmt) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, -1, fmt));
+}
+
+const std::string
+sc_fxval_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));
+}
+
+const std::string
+sc_fxval_fast::to_dec() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_DEC, -1, SC_E));
+}
+
+const std::string
+sc_fxval_fast::to_bin() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_BIN, -1, SC_E));
+}
+
+const std::string
+sc_fxval_fast::to_oct() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_OCT, -1, SC_E));
+}
+
+const std::string
+sc_fxval_fast::to_hex() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_HEX, -1, SC_E));
+}
+
+
+// print or dump content
+
+void
+sc_fxval_fast::print(::std::ostream &os) const
+{
+ os << sc_dt::to_string(m_val, SC_DEC, -1, SC_E);
+}
+
+void
+sc_fxval_fast::scan(::std::istream &is)
+{
+ std::string s;
+ is >> s;
+ *this = s.c_str();
+}
+
+void
+sc_fxval_fast::dump(::std::ostream &os) const
+{
+ os << "sc_fxval_fast" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "val = " << m_val << ::std::endl;
+ // TO BE COMPLETED
+ // os << "r_flag = " << m_r_flag << ::std::endl;
+ // os << "observer = ";
+ // if (m_observer != 0)
+ // m_observer->dump(os);
+ // else
+ // os << "0" << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+
+// internal use only;
+bool
+sc_fxval_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;
+}
+
+
+// protected methods and friend functions
+sc_fxval_fast_observer *
+sc_fxval_fast::lock_observer() const
+{
+ SC_ASSERT_(m_observer != 0, "lock observer failed");
+ sc_fxval_fast_observer *tmp = m_observer;
+ m_observer = 0;
+ return tmp;
+}
+
+void
+sc_fxval_fast::unlock_observer(sc_fxval_fast_observer *observer_) const
+{
+ SC_ASSERT_(observer_ != 0, "unlock observer failed");
+ m_observer = observer_;
+}
+
+#define SCFX_FAIL_IF_(cnd) \
+{ \
+ if ((cnd)) \
+ return static_cast<double>(scfx_ieee_double::nan()); \
+}
+
+double
+sc_fxval_fast::from_string(const char *s)
+{
+ SCFX_FAIL_IF_(s == 0 || *s == 0);
+
+ scfx_string s2;
+ s2 += s;
+ s2 += '\0';
+
+ bool sign_char;
+ int sign = scfx_parse_sign(s, sign_char);
+
+ sc_numrep numrep = scfx_parse_prefix(s);
+
+ int base = 0;
+
+ switch (numrep) {
+ case SC_DEC:
+ {
+ base = 10;
+ if (scfx_is_nan(s)) // special case: NaN
+ return static_cast<double>(scfx_ieee_double::nan());
+ if (scfx_is_inf(s)) // special case: Infinity
+ return static_cast<double>(scfx_ieee_double::inf(sign));
+ break;
+ }
+ case SC_BIN:
+ case SC_BIN_US:
+ {
+ SCFX_FAIL_IF_(sign_char);
+ base = 2;
+ break;
+ }
+
+ case SC_BIN_SM:
+ {
+ base = 2;
+ break;
+ }
+ case SC_OCT:
+ case SC_OCT_US:
+ {
+ SCFX_FAIL_IF_(sign_char);
+ base = 8;
+ break;
+ }
+ case SC_OCT_SM:
+ {
+ base = 8;
+ break;
+ }
+ case SC_HEX:
+ case SC_HEX_US:
+ {
+ SCFX_FAIL_IF_(sign_char);
+ base = 16;
+ break;
+ }
+ case SC_HEX_SM:
+ {
+ base = 16;
+ break;
+ }
+ case SC_CSD:
+ {
+ SCFX_FAIL_IF_(sign_char);
+ base = 2;
+ scfx_csd2tc(s2);
+ s = (const char*) s2 + 4;
+ numrep = SC_BIN;
+ break;
+ }
+ default:;// Martin, what is default???
+ }
+
+ //
+ // find end of mantissa and count the digits and points
+ //
+
+ const char *end = s;
+ bool based_point = false;
+ int int_digits = 0;
+ int frac_digits = 0;
+
+ while (*end) {
+ if (scfx_exp_start(end))
+ break;
+
+ if (*end == '.') {
+ SCFX_FAIL_IF_(based_point);
+ based_point = true;
+ } else {
+ SCFX_FAIL_IF_(!scfx_is_digit(*end, numrep));
+ if (based_point)
+ frac_digits++;
+ else
+ int_digits++;
+ }
+
+ end++;
+ }
+
+ SCFX_FAIL_IF_(int_digits == 0 && frac_digits == 0);
+
+ // [ exponent ]
+ int exponent = 0;
+ if (*end) {
+ for (const char *e = end + 2; *e; e++)
+ SCFX_FAIL_IF_(!scfx_is_digit(*e, SC_DEC));
+ exponent = std::atoi(end + 1);
+ }
+
+ //
+ // convert the mantissa
+ //
+ double integer = 0.0;
+ if (int_digits != 0) {
+ bool first_digit = true;
+
+ for (; s < end; s++) {
+ if (*s == '.')
+ break;
+
+ if (first_digit) {
+ integer = scfx_to_digit(*s, numrep);
+ switch (numrep) {
+ case SC_BIN:
+ case SC_OCT:
+ case SC_HEX:
+ {
+ if (integer >= (base >> 1))
+ integer -= base; // two's complement
+ break;
+ }
+ default:
+ ;
+ }
+ first_digit = false;
+ } else {
+ integer *= base;
+ integer += scfx_to_digit(*s, numrep);
+ }
+ }
+ }
+
+ // [ . fraction ]
+ double fraction = 0.0;
+ if (frac_digits != 0) {
+ s++; // skip '.'
+
+ bool first_digit = (int_digits == 0);
+ double scale = 1.0;
+ for (; s < end; s++) {
+ scale /= base;
+
+ if (first_digit) {
+ fraction = scfx_to_digit(*s, numrep);
+ switch (numrep) {
+ case SC_BIN:
+ case SC_OCT:
+ case SC_HEX:
+ {
+ if (fraction >= (base >> 1))
+ fraction -= base; // two's complement
+ break;
+ }
+ default:
+ ;
+ }
+ fraction *= scale;
+ first_digit = false;
+ } else {
+ fraction += scfx_to_digit(*s, numrep) * scale;
+ }
+ }
+ }
+
+ double exp =
+ (exponent != 0) ? std::pow((double) base, (double) exponent) : 1;
+
+ return (sign * (integer + fraction) * exp);
+}
+
+#undef SCFX_FAIL_IF_
+
+} // namespace sc_dt
diff --git a/src/systemc/dt/fx/sc_fxval_observer.cc b/src/systemc/dt/fx/sc_fxval_observer.cc
new file mode 100644
index 000000000..7b143ad04
--- /dev/null
+++ b/src/systemc/dt/fx/sc_fxval_observer.cc
@@ -0,0 +1,72 @@
+/*****************************************************************************
+
+ 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_fxval_observer.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_fxval_observer.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:58 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include "systemc/ext/dt/fx/sc_fxval_observer.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxval_observer
+//
+// Abstract base class for fixed-point value type observers;
+// arbitrary precision.
+// ----------------------------------------------------------------------------
+
+sc_fxval_observer *(* sc_fxval_observer::default_observer)() = 0;
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxval_fast_observer
+//
+// Abstract base class for fixed-point value type observers;
+// limited precision.
+// ----------------------------------------------------------------------------
+
+sc_fxval_fast_observer *(* sc_fxval_fast_observer::default_observer)() = 0;
+
+} // namespace sc_dt
diff --git a/src/systemc/dt/fx/scfx_mant.cc b/src/systemc/dt/fx/scfx_mant.cc
new file mode 100644
index 000000000..41f3aedcb
--- /dev/null
+++ b/src/systemc/dt/fx/scfx_mant.cc
@@ -0,0 +1,117 @@
+/*****************************************************************************
+
+ 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_mant.cpp -
+
+ 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_mant.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:58 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include "systemc/ext/dt/fx/scfx_mant.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// word memory management
+// ----------------------------------------------------------------------------
+
+class word_list // Entry in free_words bucket.
+{
+ public:
+ word_list *m_next_p;
+};
+
+static inline unsigned
+next_pow2_index(std::size_t size)
+{
+ unsigned index = scfx_find_msb(size);
+ // If this was a power of 2 we are one bucket too low.
+ if (~(UINT64_ONE << index) & size)
+ index++;
+ // If this is a 64-bit machine and we are using 32-bit words go down
+ // one slot size, as all the slots are 2x in size.
+ if (index != 0 && (sizeof(word_list) != sizeof(word))) {
+ index -= 1;
+ }
+ return index;
+}
+
+static word_list *free_words[32] = { 0 };
+
+word *
+scfx_mant::alloc_word(std::size_t size)
+{
+ const int ALLOC_SIZE = 128;
+
+ unsigned slot_index = next_pow2_index(size);
+ unsigned alloc_size = (UINT64_ONE << slot_index);
+
+ word_list*& slot = free_words[slot_index];
+
+ if (!slot) {
+ slot = new word_list[ALLOC_SIZE * alloc_size];
+ unsigned i;
+ for (i = 0; i < alloc_size * (ALLOC_SIZE - 1) ; i += alloc_size) {
+ slot[i].m_next_p = &slot[i + alloc_size];
+ }
+ slot[i].m_next_p = 0;
+ }
+
+ word *result = (word *)slot;
+ free_words[slot_index] = slot[0].m_next_p;
+ return result;
+}
+
+void
+scfx_mant::free_word(word *array, std::size_t size)
+{
+ if (array && size) {
+ int slot_index = next_pow2_index(size);
+ word_list *wl_p = (word_list *)array;
+
+ wl_p->m_next_p = free_words[slot_index];
+ free_words[slot_index] = wl_p;
+ }
+}
+
+} // namespace sc_dt
diff --git a/src/systemc/dt/fx/scfx_pow10.cc b/src/systemc/dt/fx/scfx_pow10.cc
new file mode 100644
index 000000000..fd940f94e
--- /dev/null
+++ b/src/systemc/dt/fx/scfx_pow10.cc
@@ -0,0 +1,129 @@
+/*****************************************************************************
+
+ 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_pow10.cpp -
+
+ 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_pow10.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:58 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include "systemc/ext/dt/fx/scfx_pow10.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// CLASS : scfx_pow10
+//
+// Class to compute (and cache) powers of 10 in arbitrary precision.
+// ----------------------------------------------------------------------------
+
+scfx_pow10::scfx_pow10()
+{
+ m_pos[0] = scfx_rep(10.0);
+ m_neg[0] = scfx_rep(0.1);
+
+ for (int i = 1; i < SCFX_POW10_TABLE_SIZE; i++) {
+ m_pos[i].set_nan();
+ m_neg[i].set_nan();
+ }
+}
+
+scfx_pow10::~scfx_pow10() {}
+
+const scfx_rep
+scfx_pow10::operator() (int i)
+{
+ if (i == 0) {
+ return scfx_rep(1.0);
+ }
+
+ if (i > 0) {
+ int bit = scfx_find_msb(i);
+ scfx_rep result = *pos(bit);
+ if (bit) {
+ while (--bit >= 0) {
+ if ((1 << bit) & i) {
+ scfx_rep *tmp = mult_scfx_rep(result, *pos(bit));
+ result = *tmp;
+ delete tmp;
+ }
+ }
+ }
+ return result;
+ } else {
+ i = -i;
+ int bit = scfx_find_msb(i);
+ scfx_rep result = *neg(bit);
+ if (bit) {
+ while (--bit >= 0) {
+ if ((1 << bit) & i) {
+ scfx_rep *tmp = mult_scfx_rep(result, *neg(bit));
+ result = *tmp;
+ delete tmp;
+ }
+ }
+ }
+ return result;
+ }
+}
+
+
+scfx_rep *
+scfx_pow10::pos(int i)
+{
+ if (!m_pos[i].is_normal()) {
+ multiply(m_pos[i], *pos(i - 1), *pos(i - 1));
+ }
+ return &m_pos[i];
+}
+
+scfx_rep *
+scfx_pow10::neg(int i)
+{
+ if (!m_neg[i].is_normal()) {
+ multiply(m_neg[i], *neg(i - 1), *neg(i - 1));
+ }
+ return &m_neg[i];
+}
+
+} // namespace sc_dt
diff --git a/src/systemc/dt/fx/scfx_rep.cc b/src/systemc/dt/fx/scfx_rep.cc
new file mode 100644
index 000000000..3d10fb3f6
--- /dev/null
+++ b/src/systemc/dt/fx/scfx_rep.cc
@@ -0,0 +1,2651 @@
+/*****************************************************************************
+
+ 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.cpp -
+
+ 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.cpp,v $
+// Revision 1.4 2011/08/24 22:05:43 acg
+// Torsten Maehne: initialization changes to remove warnings.
+//
+// Revision 1.3 2011/08/15 16:43:24 acg
+// Torsten Maehne: changes to remove unused argument warnings.
+//
+// Revision 1.2 2009/02/28 00:26:20 acg
+// Andy Goodrich: bug fixes.
+//
+// Revision 1.2 2008/11/06 17:22:47 acg
+// Andy Goodrich: bug fixes for 2.2.1.
+//
+// Revision 1.1.1.1 2006/12/15 20:31:36 acg
+// SystemC 2.2
+//
+// Revision 1.3 2006/01/13 18:53:58 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include <cctype>
+#include <cmath>
+#include <cstdio>
+#include <cstdlib>
+
+#include "base/compiler.hh"
+#include "systemc/ext/dt/bit/sc_bv_base.hh"
+#include "systemc/ext/dt/bit/sc_lv_base.hh"
+#include "systemc/ext/dt/fx/scfx_ieee.hh"
+#include "systemc/ext/dt/fx/scfx_pow10.hh"
+#include "systemc/ext/dt/fx/scfx_rep.hh"
+#include "systemc/ext/dt/fx/scfx_utils.hh"
+#include "systemc/ext/utils/endian.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// some utilities
+// ----------------------------------------------------------------------------
+
+static scfx_pow10 pow10_fx;
+
+static const int mantissa0_size = SCFX_IEEE_DOUBLE_M_SIZE - bits_in_int;
+
+static inline int
+n_word(int x)
+{
+ return (x + bits_in_word - 1) / bits_in_word;
+}
+
+
+// ----------------------------------------------------------------------------
+// CONSTRUCTORS
+// ----------------------------------------------------------------------------
+
+scfx_rep::scfx_rep() :
+ m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
+ m_r_flag(false)
+{
+ set_zero();
+}
+
+scfx_rep::scfx_rep(int a) : m_mant(min_mant), m_wp(), m_sign(), m_state(),
+ m_msw(), m_lsw(), m_r_flag(false)
+{
+ if (a != 0) {
+ m_mant.clear();
+ m_wp = m_msw = m_lsw = 2;
+ m_state = normal;
+ if (a > 0) {
+ m_mant[2] = a;
+ m_sign = 1;
+ } else {
+ m_mant[2] = -a;
+ m_sign = -1;
+ }
+ } else {
+ set_zero();
+ }
+}
+
+scfx_rep::scfx_rep(unsigned int a) : m_mant(min_mant), m_wp(), m_sign(),
+ m_state(), m_msw(), m_lsw(), m_r_flag(false)
+{
+ if (a != 0) {
+ m_mant.clear();
+ m_wp = m_msw = m_lsw = 2;
+ m_state = normal;
+ m_mant[2] = a;
+ m_sign = 1;
+ } else {
+ set_zero();
+ }
+}
+
+scfx_rep::scfx_rep(long a) :
+ m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
+ m_r_flag(false)
+{
+ if (a != 0) {
+ m_mant.clear();
+ m_state = normal;
+ if (a > 0) {
+ m_sign = 1;
+ } else {
+ a = -a;
+ m_sign = -1;
+ }
+# if defined(SC_LONG_64)
+ m_wp = 1;
+ m_mant[1] = static_cast<word>(a);
+ m_mant[2] = static_cast<word>(a >> bits_in_word);
+ find_sw();
+# else
+ m_wp = 2;
+ m_msw = 2;
+ m_lsw = 2;
+ m_mant[2] = a;
+# endif
+ } else {
+ set_zero();
+ }
+}
+
+scfx_rep::scfx_rep(unsigned long a) :
+ m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
+ m_r_flag(false)
+{
+ if (a != 0) {
+ m_mant.clear();
+ m_wp = m_msw = m_lsw = 2;
+ m_state = normal;
+# if defined(SC_LONG_64)
+ m_wp = 1;
+ m_mant[1] = static_cast<word>(a);
+ m_mant[2] = static_cast<word>(a >> bits_in_word);
+ find_sw();
+# else
+ m_wp = 2;
+ m_msw = 2;
+ m_lsw = 2;
+ m_mant[2] = a;
+# endif
+ m_sign = 1;
+ }
+ else
+ set_zero();
+}
+
+scfx_rep::scfx_rep(double a) :
+ m_mant(min_mant), m_wp(0), m_sign(), m_state(normal), m_msw(0),
+ m_lsw(0), m_r_flag(false)
+{
+ m_mant.clear();
+
+ scfx_ieee_double id(a);
+
+ m_sign = id.negative() ? -1 : 1;
+
+ if (id.is_nan()) {
+ m_state = not_a_number;
+ } else if (id.is_inf()) {
+ m_state = infinity;
+ } else if (id.is_subnormal()) {
+ m_mant[0] = id.mantissa1();
+ m_mant[1] = id.mantissa0();
+ normalize(id.exponent() + 1 - SCFX_IEEE_DOUBLE_M_SIZE);
+ } else if (id.is_normal()) {
+ m_mant[0] = id.mantissa1();
+ m_mant[1] = id.mantissa0() | (1 << mantissa0_size);
+ normalize(id.exponent() - SCFX_IEEE_DOUBLE_M_SIZE);
+ }
+}
+
+scfx_rep::scfx_rep(int64 a) :
+ m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
+ m_r_flag(false)
+{
+ if (a != 0) {
+ m_mant.clear();
+ m_wp = 1;
+ m_state = normal;
+ if (a > 0) {
+ m_mant[1] = static_cast<word>(a);
+ m_mant[2] = static_cast<word>(a >> bits_in_word);
+ m_sign = 1;
+ } else {
+ m_mant[1] = static_cast<word>(-a);
+ m_mant[2] = static_cast<word>((-a) >> bits_in_word);
+ m_sign = -1;
+ }
+ find_sw();
+ } else {
+ set_zero();
+ }
+}
+
+scfx_rep::scfx_rep(uint64 a) :
+ m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
+ m_r_flag(false)
+{
+ if (a != 0) {
+ m_mant.clear();
+ m_wp = 1;
+ m_state = normal;
+ m_mant[1] = static_cast<word>(a);
+ m_mant[2] = static_cast<word>(a >> bits_in_word);
+ m_sign = 1;
+ find_sw();
+ } else {
+ set_zero();
+ }
+}
+
+scfx_rep::scfx_rep(const sc_signed &a) :
+ m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
+ m_r_flag(false)
+{
+ if (a.iszero()) {
+ set_zero();
+ } else {
+ int words = n_word(a.length());
+ if (words > size())
+ resize_to(words);
+ m_mant.clear();
+ m_wp = 0;
+ m_state = normal;
+ if (a.sign()) {
+ sc_signed a2 = -a;
+ for (int i = 0; i < a2.length(); ++i) {
+ if (a2[i]) {
+ scfx_index x = calc_indices(i);
+ m_mant[x.wi()] |= 1 << x.bi();
+ }
+ }
+ m_sign = -1;
+ } else {
+ for (int i = 0; i < a.length(); ++i) {
+ if (a[i]) {
+ scfx_index x = calc_indices(i);
+ m_mant[x.wi()] |= 1 << x.bi();
+ }
+ }
+ m_sign = 1;
+ }
+ find_sw();
+ }
+}
+
+scfx_rep::scfx_rep(const sc_unsigned &a) :
+ m_mant(min_mant), m_wp(), m_sign(), m_state(), m_msw(), m_lsw(),
+ m_r_flag(false)
+{
+ if (a.iszero()) {
+ set_zero();
+ } else {
+ int words = n_word(a.length());
+ if (words > size())
+ resize_to(words);
+ m_mant.clear();
+ m_wp = 0;
+ m_state = normal;
+ for (int i = 0; i < a.length(); ++i) {
+ if (a[i]) {
+ scfx_index x = calc_indices(i);
+ m_mant[x.wi()] |= 1 << x.bi();
+ }
+ }
+ m_sign = 1;
+ find_sw();
+ }
+}
+
+// copy constructor
+scfx_rep::scfx_rep(const scfx_rep &a) :
+ m_mant(a.m_mant), m_wp(a.m_wp), m_sign(a.m_sign), m_state(a.m_state),
+ m_msw(a.m_msw), m_lsw(a.m_lsw), m_r_flag(false)
+{}
+
+
+// ----------------------------------------------------------------------------
+// OPERATORS : new, delete
+//
+// Memory management for class scfx_rep.
+// ----------------------------------------------------------------------------
+
+union scfx_rep_node
+{
+ char data[sizeof(scfx_rep)];
+ scfx_rep_node *next;
+};
+
+static scfx_rep_node *list = 0;
+
+void *
+scfx_rep::operator new(std::size_t size)
+{
+ const int ALLOC_SIZE = 1024;
+
+ if (size != sizeof(scfx_rep))
+ return ::operator new(size);
+
+ if (!list) {
+ list = new scfx_rep_node[ALLOC_SIZE];
+ for (int i = 0; i < ALLOC_SIZE - 1; i++)
+ list[i].next = list + i + 1;
+ list[ALLOC_SIZE - 1].next = 0;
+ }
+
+ scfx_rep *ptr = reinterpret_cast<scfx_rep *>(list->data);
+ list = list->next;
+
+ return ptr;
+}
+
+void
+scfx_rep::operator delete(void *ptr, std::size_t size)
+{
+ if (size != sizeof(scfx_rep)) {
+ ::operator delete(ptr);
+ return;
+ }
+
+ scfx_rep_node *node = static_cast<scfx_rep_node *>(ptr);
+ node->next = list;
+ list = node;
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : from_string
+//
+// Convert from character string to sc_fxrep.
+// ----------------------------------------------------------------------------
+
+#define SCFX_FAIL_IF_(cnd) \
+{ \
+ if ((cnd)) { \
+ m_state = not_a_number; \
+ m_mant.clear(); /* to avoid Purify UMRs during assignment */ \
+ return; \
+ } \
+}
+
+void
+scfx_rep::from_string(const char *s, int cte_wl)
+{
+ SCFX_FAIL_IF_(s == 0 || *s == 0);
+
+ scfx_string s2;
+ s2 += s;
+ s2 += '\0';
+
+ bool sign_char;
+ m_sign = scfx_parse_sign(s, sign_char);
+
+ sc_numrep numrep = scfx_parse_prefix(s);
+
+ int base = 0;
+
+ switch (numrep) {
+ case SC_DEC:
+ {
+ base = 10;
+ if (scfx_is_nan(s)) { // special case: NaN
+ m_state = not_a_number;
+ m_mant.clear(); /* to avoid Purify UMRs during assignment */
+ return;
+ }
+ if (scfx_is_inf(s)) { // special case: Infinity
+ m_state = infinity;
+ m_mant.clear(); /* to avoid Purify UMRs during assignment */
+ return;
+ }
+ break;
+ }
+ case SC_BIN:
+ case SC_BIN_US:
+ {
+ SCFX_FAIL_IF_(sign_char);
+ base = 2;
+ break;
+ }
+
+ case SC_BIN_SM:
+ {
+ base = 2;
+ break;
+ }
+ case SC_OCT:
+ case SC_OCT_US:
+ {
+ SCFX_FAIL_IF_(sign_char);
+ base = 8;
+ break;
+ }
+ case SC_OCT_SM:
+ {
+ base = 8;
+ break;
+ }
+ case SC_HEX:
+ case SC_HEX_US:
+ {
+ SCFX_FAIL_IF_(sign_char);
+ base = 16;
+ break;
+ }
+ case SC_HEX_SM:
+ {
+ base = 16;
+ break;
+ }
+ case SC_CSD:
+ {
+ SCFX_FAIL_IF_(sign_char);
+ base = 2;
+ scfx_csd2tc(s2);
+ s = (const char *)s2 + 4;
+ numrep = SC_BIN;
+ break;
+ }
+ default:
+ ;
+ }
+
+ //
+ // find end of mantissa and count the digits and points
+ //
+
+ const char *end = s;
+ bool based_point = false;
+ int int_digits = 0;
+ int frac_digits = 0;
+
+ while (*end) {
+ if (scfx_exp_start(end))
+ break;
+
+ if (*end == '.') {
+ SCFX_FAIL_IF_(based_point);
+ based_point = true;
+ } else {
+ SCFX_FAIL_IF_(!scfx_is_digit(*end, numrep));
+ if (based_point)
+ frac_digits++;
+ else
+ int_digits++;
+ }
+
+ ++end;
+ }
+
+ SCFX_FAIL_IF_(int_digits == 0 && frac_digits == 0);
+
+ // [ exponent ]
+ int exponent = 0;
+
+ if (*end) {
+ for (const char *e = end + 2; *e; ++e)
+ SCFX_FAIL_IF_(!scfx_is_digit(*e, SC_DEC));
+ exponent = std::atoi(end + 1);
+ }
+
+ //
+ // check if the mantissa is negative
+ //
+ bool mant_is_neg = false;
+ switch (numrep) {
+ case SC_BIN:
+ case SC_OCT:
+ case SC_HEX:
+ {
+ const char *p = s;
+ if (*p == '.')
+ ++p;
+
+ mant_is_neg = (scfx_to_digit(* p, numrep) >= (base >> 1));
+ break;
+ }
+ default:
+ ;
+ }
+
+ //
+ // convert the mantissa
+ //
+
+ switch (base) {
+ case 2:
+ {
+ int bit_offset = exponent % bits_in_word;
+ int word_offset = exponent / bits_in_word;
+
+ int_digits += bit_offset;
+ frac_digits -= bit_offset;
+
+ int words = n_word(int_digits) + n_word(frac_digits);
+ if (words > size())
+ resize_to(words);
+ m_mant.clear();
+
+ int j = n_word(frac_digits) * bits_in_word + int_digits - 1;
+
+ for (; s < end; s++) {
+ switch (*s) {
+ case '1':
+ set_bin(j);
+ M5_FALLTHROUGH;
+ case '0':
+ j--;
+ M5_FALLTHROUGH;
+ case '.':
+ break;
+ default:
+ SCFX_FAIL_IF_(true); // should not happen
+ }
+ }
+
+ m_wp = n_word(frac_digits) - word_offset;
+ break;
+ }
+ case 8:
+ {
+ exponent *= 3;
+ int_digits *= 3;
+ frac_digits *= 3;
+
+ int bit_offset = exponent % bits_in_word;
+ int word_offset = exponent / bits_in_word;
+
+ int_digits += bit_offset;
+ frac_digits -= bit_offset;
+
+ int words = n_word(int_digits) + n_word(frac_digits);
+ if (words > size())
+ resize_to(words);
+ m_mant.clear();
+
+ int j = n_word(frac_digits) * bits_in_word + int_digits - 3;
+
+ for (; s < end; s++) {
+ switch (*s) {
+ case '7': case '6': case '5': case '4':
+ case '3': case '2': case '1':
+ set_oct(j, *s - '0');
+ M5_FALLTHROUGH;
+ case '0':
+ j -= 3;
+ M5_FALLTHROUGH;
+ case '.':
+ break;
+ default:
+ SCFX_FAIL_IF_(true); // should not happen
+ }
+ }
+
+ m_wp = n_word(frac_digits) - word_offset;
+ break;
+ }
+ case 10:
+ {
+ word carry, temp;
+ int length = int_digits + frac_digits;
+ resize_to(sc_max(min_mant, n_word(4 * length)));
+
+ m_mant.clear();
+ m_msw = m_lsw = 0;
+
+ for (; s < end; s++) {
+ switch (*s) {
+ case '9': case '8': case '7': case '6': case '5':
+ case '4': case '3': case '2': case '1': case '0':
+ multiply_by_ten();
+ carry = *s - '0';
+ for (int i = 0; carry && i < m_mant.size(); i++) {
+ temp = m_mant[i];
+ temp += carry;
+ carry = temp < m_mant[i];
+ m_mant[i] = temp;
+ }
+ case '.':
+ break;
+ default:
+ SCFX_FAIL_IF_(true); // should not happen
+ }
+ }
+
+ m_wp = 0;
+ find_sw();
+
+ int denominator = frac_digits - exponent;
+
+ if (denominator) {
+ scfx_rep frac_num = pow10_fx(denominator);
+ scfx_rep *temp_num =
+ div_scfx_rep(const_cast<const scfx_rep &>(*this),
+ frac_num, cte_wl);
+ *this = *temp_num;
+ delete temp_num;
+ }
+
+ break;
+ }
+ case 16:
+ {
+ exponent *= 4;
+ int_digits *= 4;
+ frac_digits *= 4;
+
+ int bit_offset = exponent % bits_in_word;
+ int word_offset = exponent / bits_in_word;
+
+ int_digits += bit_offset;
+ frac_digits -= bit_offset;
+
+ int words = n_word(int_digits) + n_word(frac_digits);
+ if (words > size())
+ resize_to(words);
+ m_mant.clear();
+
+ int j = n_word(frac_digits) * bits_in_word + int_digits - 4;
+
+ for (; s < end; s ++) {
+ switch (*s) {
+ case 'f': case 'e': case 'd': case 'c': case 'b': case 'a':
+ set_hex(j, *s - 'a' + 10);
+ j -= 4;
+ break;
+ case 'F': case 'E': case 'D': case 'C': case 'B': case 'A':
+ set_hex(j, *s - 'A' + 10);
+ j -= 4;
+ break;
+ case '9': case '8': case '7': case '6': case '5':
+ case '4': case '3': case '2': case '1':
+ set_hex(j, *s - '0');
+ M5_FALLTHROUGH;
+ case '0':
+ j -= 4;
+ M5_FALLTHROUGH;
+ case '.':
+ break;
+ default:
+ SCFX_FAIL_IF_(true); // should not happen
+ }
+ }
+
+ m_wp = n_word(frac_digits) - word_offset;
+ break;
+ }
+ }
+
+ m_state = normal;
+ find_sw();
+
+ //
+ // two's complement of mantissa if it is negative
+ //
+ if (mant_is_neg) {
+ m_mant[m_msw] |= ~0U << scfx_find_msb(m_mant[m_msw]);
+ for (int i = m_msw + 1; i < m_mant.size(); ++i)
+ m_mant[i] = static_cast<word>(-1);
+ complement(m_mant, m_mant, m_mant.size());
+ inc(m_mant);
+ m_sign *= -1;
+ find_sw();
+ }
+}
+
+#undef SCFX_FAIL_IF_
+
+// ----------------------------------------------------------------------------
+// METHOD : to_double
+//
+// Convert from scfx_rep to double.
+// ----------------------------------------------------------------------------
+
+double
+scfx_rep::to_double() const
+{
+ scfx_ieee_double id;
+
+ // handle special cases
+ if (is_nan()) {
+ id.set_nan();
+ return id;
+ }
+
+ if (is_inf()) {
+ id.set_inf();
+ id.negative(m_sign < 0);
+ return id;
+ }
+
+ if (is_zero()) {
+ id = 0.;
+ id.negative(m_sign < 0);
+ return id;
+ }
+
+ int msb = scfx_find_msb(m_mant[m_msw]);
+
+ int exp = (m_msw - m_wp) * bits_in_word + msb;
+
+ if (exp > SCFX_IEEE_DOUBLE_E_MAX) {
+ id.set_inf();
+ id.negative(m_sign < 0);
+ return id;
+ }
+
+ if (exp < SCFX_IEEE_DOUBLE_E_MIN -
+ static_cast<int>(SCFX_IEEE_DOUBLE_M_SIZE))
+ {
+ id = 0.;
+ return id;
+ }
+
+ int shift = mantissa0_size - msb;
+
+ unsigned int m0;
+ unsigned int m1 = 0;
+ unsigned int guard = 0;
+
+ if (shift == 0) {
+ m0 = m_mant[m_msw] & ~(1 << mantissa0_size);
+ if (m_msw > m_lsw) {
+ m1 = m_mant[m_msw - 1];
+ if (m_msw - 1 > m_lsw)
+ guard = m_mant[m_msw - 2] >> (bits_in_word - 1);
+ }
+ } else if (shift < 0) {
+ m0 = (m_mant[m_msw] >> -shift) & ~(1 << mantissa0_size);
+ m1 = m_mant[m_msw] << (bits_in_word + shift);
+ if (m_msw > m_lsw) {
+ m1 |= m_mant[m_msw - 1] >> -shift;
+ guard = (m_mant[m_msw - 1] >> (-shift - 1)) & 1;
+ }
+ } else {
+ m0 = (m_mant[m_msw] << shift) & ~(1 << mantissa0_size);
+ if (m_msw > m_lsw) {
+ m0 |= m_mant[m_msw - 1] >> (bits_in_word - shift);
+ m1 = m_mant[m_msw - 1] << shift;
+ if (m_msw - 1 > m_lsw) {
+ m1 |= m_mant[m_msw - 2] >> (bits_in_word - shift);
+ guard = (m_mant[m_msw - 2] >> (bits_in_word - shift - 1)) & 1;
+ }
+ }
+ }
+
+ if (exp < SCFX_IEEE_DOUBLE_E_MIN) {
+ m0 |= (1 << mantissa0_size);
+
+ int subnormal_shift = SCFX_IEEE_DOUBLE_E_MIN - exp;
+
+ if (subnormal_shift < bits_in_word) {
+ m1 = m1 >> subnormal_shift |
+ m0 << (bits_in_word - subnormal_shift);
+ m0 = m0 >> subnormal_shift;
+ } else {
+ m1 = m0 >> (subnormal_shift - bits_in_word);
+ m0 = 0;
+ }
+
+ guard = 0;
+
+ exp = SCFX_IEEE_DOUBLE_E_MIN - 1;
+ }
+
+ id.mantissa0(m0);
+ id.mantissa1(m1);
+ id.exponent(exp);
+ id.negative(m_sign < 0);
+
+ double result = id;
+
+ if (guard != 0)
+ result += m_sign * scfx_pow2(exp - SCFX_IEEE_DOUBLE_M_SIZE);
+
+ return result;
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : to_uint64
+//
+// Convert from scfx_rep to uint64.
+// Truncates towards 0 _then_ wraps; infinities and NaN go to zero.
+// ----------------------------------------------------------------------------
+
+uint64
+scfx_rep::to_uint64() const
+{
+ if (!is_normal() || is_zero()) {
+ return 0;
+ }
+
+ uint64 result = 0;
+ int shift = 0;
+ int idx = m_wp;
+
+ // Ignore bits off the top; they modulo out.
+ // Ignore bits off the bottom; we're truncating.
+ while (shift < 64 && m_msw >= idx && idx >= m_lsw) {
+ result += static_cast<uint64>(m_mant[idx]) << shift;
+ shift += bits_in_word;
+ idx += 1;
+ }
+
+ return m_sign > 0 ? result : -result;
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : to_string
+//
+// Convert from scfx_rep to character string.
+// ----------------------------------------------------------------------------
+
+void
+print_dec(scfx_string &s, const scfx_rep &num, int w_prefix, sc_fmt fmt)
+{
+ if (num.is_neg())
+ s += '-';
+
+ if (w_prefix == 1) {
+ scfx_print_prefix(s, SC_DEC);
+ }
+
+ if (num.is_zero()) {
+ s += '0';
+ return;
+ }
+
+ // split 'num' into its integer and fractional part
+ scfx_rep int_part = num;
+ scfx_rep frac_part = num;
+
+ int i;
+
+ for (i = int_part.m_lsw; i <= int_part.m_msw && i < int_part.m_wp; i++)
+ int_part.m_mant[i] = 0;
+ int_part.find_sw();
+ if (int_part.m_wp < int_part.m_lsw)
+ int_part.resize_to(int_part.size() - int_part.m_wp, -1);
+
+ for (i = frac_part.m_msw;
+ i >= frac_part.m_lsw && i >= frac_part.m_wp; i--)
+ frac_part.m_mant[i] = 0;
+ frac_part.find_sw();
+ if (frac_part.m_msw == frac_part.size() - 1)
+ frac_part.resize_to(frac_part.size() + 1, 1);
+
+ // print integer part
+ int int_digits = 0;
+ int int_zeros = 0;
+
+ if (!int_part.is_zero()) {
+ double int_wl = (int_part.m_msw - int_part.m_wp) * bits_in_word +
+ scfx_find_msb(int_part.m_mant[int_part.m_msw]) + 1;
+ int_digits = (int)std::ceil(int_wl * std::log10(2.));
+
+ int len = s.length();
+ s.append(int_digits);
+
+ bool zero_digits = (frac_part.is_zero() && fmt != SC_F);
+
+ for (i = int_digits + len - 1; i >= len; i--) {
+ unsigned int remainder = int_part.divide_by_ten();
+ s[i] = static_cast<char>('0' + remainder);
+
+ if (zero_digits) {
+ if (remainder == 0)
+ int_zeros++;
+ else
+ zero_digits = false;
+ }
+ }
+
+ // discard trailing zeros from int_part
+ s.discard(int_zeros);
+
+ if (s[len] == '0') {
+ // int_digits was overestimated by one
+ s.remove(len);
+ --int_digits;
+ }
+ }
+
+ // print fractional part
+ int frac_digits = 0;
+ int frac_zeros = 0;
+
+ if (!frac_part.is_zero()) {
+ s += '.';
+
+ bool zero_digits = (int_digits == 0 && fmt != SC_F);
+
+ double frac_wl = (frac_part.m_wp - frac_part.m_msw) * bits_in_word -
+ scfx_find_msb(frac_part.m_mant[frac_part.m_msw]) - 1;
+ frac_zeros = (int)std::floor(frac_wl * std::log10(2.));
+
+ scfx_rep temp;
+ sc_dt::multiply(temp, frac_part, pow10_fx(frac_zeros));
+ frac_part = temp;
+ if (frac_part.m_msw == frac_part.size() - 1)
+ frac_part.resize_to(frac_part.size() + 1, 1);
+
+ frac_digits = frac_zeros;
+ if (!zero_digits) {
+ for (i = 0; i < frac_zeros; i++)
+ s += '0';
+ frac_zeros = 0;
+ }
+
+ while (!frac_part.is_zero()) {
+ frac_part.multiply_by_ten();
+ int n = frac_part.m_mant[frac_part.m_msw + 1];
+
+ if (zero_digits) {
+ if (n == 0)
+ frac_zeros++;
+ else
+ zero_digits = false;
+ }
+
+ if (! zero_digits)
+ s += static_cast<char>('0' + n);
+
+ frac_part.m_mant[frac_part.m_msw + 1] = 0;
+ frac_digits++;
+ }
+ }
+
+ // print exponent
+ if (fmt != SC_F) {
+ if (frac_digits == 0)
+ scfx_print_exp(s, int_zeros);
+ else if (int_digits == 0)
+ scfx_print_exp(s, -frac_zeros);
+ }
+}
+
+void
+print_other(scfx_string &s, const scfx_rep &a, sc_numrep numrep, int w_prefix,
+ sc_fmt fmt, const scfx_params *params)
+{
+ scfx_rep b = a;
+
+ sc_numrep numrep2 = numrep;
+
+ bool numrep_is_sm = (numrep == SC_BIN_SM ||
+ numrep == SC_OCT_SM ||
+ numrep == SC_HEX_SM);
+
+ if (numrep_is_sm) {
+ if (b.is_neg()) {
+ s += '-';
+ b = *neg_scfx_rep(a);
+ }
+ switch (numrep) {
+ case SC_BIN_SM:
+ numrep2 = SC_BIN_US;
+ break;
+ case SC_OCT_SM:
+ numrep2 = SC_OCT_US;
+ break;
+ case SC_HEX_SM:
+ numrep2 = SC_HEX_US;
+ break;
+ default:
+ ;
+ }
+ }
+
+ if (w_prefix != 0) {
+ scfx_print_prefix(s, numrep);
+ }
+
+ numrep = numrep2;
+
+ int msb, lsb;
+
+ if (params != 0) {
+ msb = params->iwl() - 1;
+ lsb = params->iwl() - params->wl();
+
+ if (params->enc() == SC_TC_ &&
+ (numrep == SC_BIN_US ||
+ numrep == SC_OCT_US ||
+ numrep == SC_HEX_US) &&
+ !numrep_is_sm &&
+ params->wl() > 1) {
+ --msb;
+ } else if (params->enc() == SC_US_ &&
+ (numrep == SC_BIN ||
+ numrep == SC_OCT ||
+ numrep == SC_HEX ||
+ numrep == SC_CSD)) {
+ ++msb;
+ }
+ } else {
+ if (b.is_zero()) {
+ msb = 0;
+ lsb = 0;
+ } else {
+ msb = (b.m_msw - b.m_wp) * bits_in_word
+ + scfx_find_msb(b.m_mant[ b.m_msw ]) + 1;
+ while (b.get_bit(msb) == b.get_bit(msb - 1))
+ --msb;
+
+ if (numrep == SC_BIN_US ||
+ numrep == SC_OCT_US ||
+ numrep == SC_HEX_US) {
+ --msb;
+ }
+
+ lsb = (b.m_lsw - b.m_wp) * bits_in_word +
+ scfx_find_lsb(b.m_mant[b.m_lsw]);
+ }
+ }
+
+ int step;
+
+ switch (numrep) {
+ case SC_BIN:
+ case SC_BIN_US:
+ case SC_CSD:
+ step = 1;
+ break;
+ case SC_OCT:
+ case SC_OCT_US:
+ step = 3;
+ break;
+ case SC_HEX:
+ case SC_HEX_US:
+ step = 4;
+ break;
+ default:
+ SC_REPORT_FATAL("assertion failed", "unexpected sc_numrep");
+ sc_core::sc_abort();
+ }
+
+ msb = (int)std::ceil(double(msb + 1) / step) * step - 1;
+
+ lsb = (int)std::floor(double(lsb) / step) * step;
+
+ if (msb < 0) {
+ s += '.';
+ if (fmt == SC_F) {
+ int sign = (b.is_neg()) ? (1 << step) - 1 : 0;
+ for (int i = (msb + 1) / step; i < 0; i++) {
+ if (sign < 10)
+ s += static_cast<char>(sign + '0');
+ else
+ s += static_cast<char>(sign + 'a' - 10);
+ }
+ }
+ }
+
+ int i = msb;
+ while (i >= lsb) {
+ int value = 0;
+ for (int j = step - 1; j >= 0; --j) {
+ value += static_cast<int>(b.get_bit(i)) << j;
+ --i;
+ }
+ if (value < 10)
+ s += static_cast<char>(value + '0');
+ else
+ s += static_cast<char>(value + 'a' - 10);
+ if (i == -1)
+ s += '.';
+ }
+
+ if (lsb > 0 && fmt == SC_F) {
+ for (int i = lsb / step; i > 0; i--)
+ s += '0';
+ }
+
+ if (s[s.length() - 1] == '.')
+ s.discard(1);
+
+ if (fmt != SC_F) {
+ if (msb < 0)
+ scfx_print_exp(s, (msb + 1) / step);
+ else if (lsb > 0)
+ scfx_print_exp(s, lsb / step);
+ }
+
+ if (numrep == SC_CSD)
+ scfx_tc2csd(s, w_prefix);
+}
+
+const char *
+scfx_rep::to_string(sc_numrep numrep, int w_prefix,
+ sc_fmt fmt, const scfx_params *params) const
+{
+ static scfx_string s;
+
+ s.clear();
+
+ if (is_nan()) {
+ scfx_print_nan(s);
+ } else if (is_inf()) {
+ scfx_print_inf(s, is_neg());
+ } else if (is_neg() && !is_zero() &&
+ (numrep == SC_BIN_US ||
+ numrep == SC_OCT_US ||
+ numrep == SC_HEX_US)) {
+ s += "negative";
+ } else if (numrep == SC_DEC || numrep == SC_NOBASE) {
+ sc_dt::print_dec(s, *this, w_prefix, fmt);
+ } else {
+ sc_dt::print_other(s, *this, numrep, w_prefix, fmt, params);
+ }
+
+ return s;
+}
+
+
+// ----------------------------------------------------------------------------
+// ADD
+//
+// add two mantissas of the same size
+// result has the same size
+// returns carry of operation
+// ----------------------------------------------------------------------------
+
+static inline int
+add_mants(int size, scfx_mant &result, const scfx_mant &a, const scfx_mant &b)
+{
+ unsigned int carry = 0;
+
+ int index = 0;
+
+ do {
+ word x = a[index];
+ word y = b[index];
+
+ y += carry;
+ carry = y < carry;
+ y += x;
+ carry += y < x;
+ result[index] = y;
+ } while (++index < size);
+
+ return (carry ? 1 : 0);
+}
+
+static inline int
+sub_mants(int size, scfx_mant &result, const scfx_mant &a, const scfx_mant &b)
+{
+ unsigned carry = 0;
+
+ int index = 0;
+
+ do {
+ word x = a[index];
+ word y = b[index];
+
+ y += carry;
+ carry = y < carry;
+ y = x - y;
+ carry += y > x;
+ result[index] = y;
+ } while (++index < size);
+
+ return (carry ? 1 : 0);
+}
+
+scfx_rep *
+add_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int max_wl)
+{
+ scfx_rep &result = *new scfx_rep;
+
+ //
+ // check for special cases
+ //
+ if (lhs.is_nan() || rhs.is_nan() ||
+ (lhs.is_inf() && rhs.is_inf() && lhs.m_sign != rhs.m_sign)) {
+ result.set_nan();
+ return &result;
+ }
+
+ if (lhs.is_inf()) {
+ result.set_inf(lhs.m_sign);
+ return &result;
+ }
+
+ if (rhs.is_inf()) {
+ result.set_inf(rhs.m_sign);
+ return &result;
+ }
+
+ //
+ // align operands if needed
+ //
+ scfx_mant_ref lhs_mant;
+ scfx_mant_ref rhs_mant;
+
+ int len_mant = lhs.size();
+ int new_wp = lhs.m_wp;
+
+ align(lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant);
+
+ //
+ // size the result mantissa
+ //
+ result.resize_to(len_mant);
+ result.m_wp = new_wp;
+
+ //
+ // do it
+ //
+ if (lhs.m_sign == rhs.m_sign) {
+ add_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
+ result.m_sign = lhs.m_sign;
+ } else {
+ int cmp = compare_abs(lhs, rhs);
+
+ if (cmp == 1) {
+ sub_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
+ result.m_sign = lhs.m_sign;
+ } else if (cmp == -1) {
+ sub_mants(len_mant, result.m_mant, rhs_mant, lhs_mant);
+ result.m_sign = rhs.m_sign;
+ } else {
+ result.m_mant.clear();
+ result.m_sign = 1;
+ }
+ }
+
+ result.find_sw();
+ result.round(max_wl);
+
+ return &result;
+}
+
+
+// ----------------------------------------------------------------------------
+// SUB
+//
+// sub two word's of the same size
+// result has the same size
+// returns carry of operation
+// ----------------------------------------------------------------------------
+
+static inline int
+sub_with_index(scfx_mant &a, int a_msw, int /*a_lsw*/,
+ const scfx_mant &b, int b_msw, int b_lsw)
+{
+ unsigned carry = 0;
+
+ int size = b_msw - b_lsw;
+ int a_index = a_msw - size;
+ int b_index = b_msw - size;
+
+ do {
+ word x = a[a_index];
+ word y = b[b_index];
+
+ y += carry;
+ carry = y < carry;
+ y = x - y;
+ carry += y > x;
+ a[a_index] = y;
+
+ a_index++;
+ b_index++;
+ } while (size--);
+
+ if (carry) {
+ // special case: a[a_msw + 1] == 1
+ a[a_msw + 1] = 0;
+ }
+
+ return (carry ? 1 : 0);
+}
+
+scfx_rep *
+sub_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int max_wl)
+{
+ scfx_rep &result = *new scfx_rep;
+
+ //
+ // check for special cases
+ //
+ if (lhs.is_nan() || rhs.is_nan() ||
+ (lhs.is_inf() && rhs.is_inf() && lhs.m_sign == rhs.m_sign)) {
+ result.set_nan();
+ return &result;
+ }
+
+ if (lhs.is_inf()) {
+ result.set_inf(lhs.m_sign);
+ return &result;
+ }
+
+ if (rhs.is_inf()) {
+ result.set_inf(-1 * rhs.m_sign);
+ return &result;
+ }
+
+ //
+ // align operands if needed
+ //
+ scfx_mant_ref lhs_mant;
+ scfx_mant_ref rhs_mant;
+
+ int len_mant = lhs.size();
+ int new_wp = lhs.m_wp;
+
+ align(lhs, rhs, new_wp, len_mant, lhs_mant, rhs_mant);
+
+ //
+ // size the result mantissa
+ //
+ result.resize_to(len_mant);
+ result.m_wp = new_wp;
+
+ //
+ // do it
+ //
+ if (lhs.m_sign != rhs.m_sign) {
+ add_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
+ result.m_sign = lhs.m_sign;
+ } else {
+ int cmp = compare_abs(lhs, rhs);
+
+ if (cmp == 1) {
+ sub_mants(len_mant, result.m_mant, lhs_mant, rhs_mant);
+ result.m_sign = lhs.m_sign;
+ } else if (cmp == -1) {
+ sub_mants(len_mant, result.m_mant, rhs_mant, lhs_mant);
+ result.m_sign = -rhs.m_sign;
+ } else {
+ result.m_mant.clear();
+ result.m_sign = 1;
+ }
+ }
+
+ result.find_sw();
+ result.round(max_wl);
+
+ return &result;
+}
+
+
+// ----------------------------------------------------------------------------
+// MUL
+// ----------------------------------------------------------------------------
+
+union word_short
+{
+ word l;
+ struct
+ {
+#if defined(SC_BOOST_BIG_ENDIAN)
+ half_word u;
+ half_word l;
+#elif defined(SC_BOOST_LITTLE_ENDIAN)
+ half_word l;
+ half_word u;
+#endif
+ } s;
+};
+
+#if defined(SC_BOOST_BIG_ENDIAN)
+static const int half_word_incr = -1;
+#elif defined(SC_BOOST_LITTLE_ENDIAN)
+static const int half_word_incr = 1;
+#endif
+
+void
+multiply(scfx_rep &result, const scfx_rep &lhs, const scfx_rep &rhs,
+ int max_wl)
+{
+ //
+ // check for special cases
+ //
+ if (lhs.is_nan() || rhs.is_nan() ||
+ (lhs.is_inf() && rhs.is_zero()) ||
+ (lhs.is_zero() && rhs.is_inf())) {
+ result.set_nan();
+ return;
+ }
+
+ if (lhs.is_inf() || rhs.is_inf()) {
+ result.set_inf(lhs.m_sign * rhs.m_sign);
+ return;
+ }
+
+ if (lhs.is_zero() || rhs.is_zero()) {
+ result.set_zero(lhs.m_sign * rhs.m_sign);
+ return;
+ }
+
+ //
+ // do it
+ //
+ int len_lhs = lhs.m_msw - lhs.m_lsw + 1;
+ int len_rhs = rhs.m_msw - rhs.m_lsw + 1;
+
+ int new_size = sc_max(min_mant, len_lhs + len_rhs);
+ int new_wp = (lhs.m_wp - lhs.m_lsw) + (rhs.m_wp - rhs.m_lsw);
+ int new_sign = lhs.m_sign * rhs.m_sign;
+
+ result.resize_to(new_size);
+ result.m_mant.clear();
+ result.m_wp = new_wp;
+ result.m_sign = new_sign;
+ result.m_state = scfx_rep::normal;
+
+ half_word *s1 = lhs.m_mant.half_addr(lhs.m_lsw);
+ half_word *s2 = rhs.m_mant.half_addr(rhs.m_lsw);
+
+ half_word *t = result.m_mant.half_addr();
+
+ len_lhs <<= 1;
+ len_rhs <<= 1;
+
+ int i1, i2;
+
+ for (i1 = 0; i1 * half_word_incr < len_lhs; i1 += half_word_incr) {
+ word_short ls;
+ ls.l = 0;
+
+ half_word v1 = s1[i1];
+
+ for (i2 = 0; i2 * half_word_incr < len_rhs; i2 += half_word_incr) {
+ ls.l += v1 * s2[i2];
+ ls.s.l = ls.s.u + ((t[i2] += ls.s.l) < ls.s.l);
+ ls.s.u = 0;
+ }
+
+ t[i2] = ls.s.l;
+ t += half_word_incr;
+ }
+
+ result.find_sw();
+ result.round(max_wl);
+}
+
+
+// ----------------------------------------------------------------------------
+// DIV
+// ----------------------------------------------------------------------------
+
+scfx_rep *
+div_scfx_rep(const scfx_rep &lhs, const scfx_rep &rhs, int div_wl)
+{
+ scfx_rep &result = *new scfx_rep;
+
+ //
+ // check for special cases
+ //
+ if (lhs.is_nan() || rhs.is_nan() || (lhs.is_inf() && rhs.is_inf()) ||
+ (lhs.is_zero() && rhs.is_zero())) {
+ result.set_nan();
+ return &result;
+ }
+
+ if (lhs.is_inf() || rhs.is_zero()) {
+ result.set_inf(lhs.m_sign * rhs.m_sign);
+ return &result;
+ }
+
+ if (lhs.is_zero() || rhs.is_inf()) {
+ result.set_zero(lhs.m_sign * rhs.m_sign);
+ return &result;
+ }
+
+ //
+ // do it
+ //
+
+ // compute one bit more for rounding
+ div_wl++;
+
+ result.resize_to(sc_max(n_word(div_wl) + 1, min_mant));
+ result.m_mant.clear();
+ result.m_sign = lhs.m_sign * rhs.m_sign;
+
+ int msb_lhs = scfx_find_msb(lhs.m_mant[lhs.m_msw]) +
+ (lhs.m_msw - lhs.m_wp) * bits_in_word;
+ int msb_rhs = scfx_find_msb(rhs.m_mant[rhs.m_msw]) +
+ (rhs.m_msw - rhs.m_wp) * bits_in_word;
+
+ int msb_res = msb_lhs - msb_rhs;
+ int to_shift = -msb_res % bits_in_word;
+ int result_index;
+
+ int c = (msb_res % bits_in_word >= 0) ? 1 : 0;
+
+ result_index = (result.size() - c) * bits_in_word + msb_res % bits_in_word;
+ result.m_wp = (result.size() - c) - msb_res / bits_in_word;
+
+ scfx_rep remainder = lhs;
+
+ // align msb from remainder to msb from rhs
+ remainder.lshift(to_shift);
+
+ // make sure msw(remainder) < size - 1
+ if (remainder.m_msw == remainder.size() - 1)
+ remainder.resize_to(remainder.size() + 1, 1);
+
+ // make sure msw(remainder) >= msw(rhs)!
+ int msw_diff = rhs.m_msw - remainder.m_msw;
+ if (msw_diff > 0)
+ remainder.resize_to(remainder.size() + msw_diff, -1);
+
+ int counter;
+
+ for (counter = div_wl; counter && !remainder.is_zero(); counter--) {
+ if (compare_msw_ff(rhs, remainder) <= 0) {
+ result.set_bin(result_index);
+ sub_with_index(remainder.m_mant, remainder.m_msw, remainder.m_lsw,
+ rhs.m_mant, rhs.m_msw, rhs.m_lsw);
+ }
+ result_index--;
+ remainder.shift_left(1);
+ remainder.m_lsw = remainder.find_lsw();
+ }
+
+ // perform convergent rounding, if needed
+ if (counter == 0) {
+ int index = result_index + 1 - result.m_wp * bits_in_word;
+
+ scfx_index x = result.calc_indices(index);
+ scfx_index x1 = result.calc_indices(index + 1);
+
+ if (result.o_bit_at(x) && result.o_bit_at(x1))
+ result.q_incr(x);
+
+ result.m_r_flag = true;
+ }
+
+ result.find_sw();
+
+ return &result;
+}
+
+// ----------------------------------------------------------------------------
+// destructive shift mantissa to the left
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::lshift(int n)
+{
+ if (n == 0)
+ return;
+
+ if (n < 0) {
+ rshift(-n);
+ return;
+ }
+
+ if (is_normal()) {
+ int shift_bits = n % bits_in_word;
+ int shift_words = n / bits_in_word;
+
+ // resize if needed
+ if (m_msw == size() - 1 &&
+ scfx_find_msb(m_mant[m_msw]) >= bits_in_word - shift_bits)
+ resize_to(size() + 1, 1);
+
+ // do it
+ m_wp -= shift_words;
+ shift_left(shift_bits);
+ find_sw();
+ }
+}
+
+// ----------------------------------------------------------------------------
+// destructive shift mantissa to the right
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::rshift(int n)
+{
+ if (n == 0)
+ return;
+
+ if (n < 0) {
+ lshift(-n);
+ return;
+ }
+
+ if (is_normal()) {
+ int shift_bits = n % bits_in_word;
+ int shift_words = n / bits_in_word;
+
+ // resize if needed
+ if (m_lsw == 0 && scfx_find_lsb(m_mant[m_lsw]) < shift_bits)
+ resize_to(size() + 1, -1);
+
+ // do it
+ m_wp += shift_words;
+ shift_right(shift_bits);
+ find_sw();
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// FRIEND FUNCTION : compare_abs
+//
+// Compares the absolute values of two scfx_reps, excluding the special cases.
+// ----------------------------------------------------------------------------
+
+int
+compare_abs(const scfx_rep &a, const scfx_rep &b)
+{
+ // check for zero
+ word a_word = a.m_mant[a.m_msw];
+ word b_word = b.m_mant[b.m_msw];
+
+ if (a_word == 0 || b_word == 0) {
+ if (a_word != 0)
+ return 1;
+ if (b_word != 0)
+ return -1;
+ return 0;
+ }
+
+ // compare msw index
+ int a_msw = a.m_msw - a.m_wp;
+ int b_msw = b.m_msw - b.m_wp;
+
+ if (a_msw > b_msw)
+ return 1;
+
+ if (a_msw < b_msw)
+ return -1;
+
+ // compare content
+ int a_i = a.m_msw;
+ int b_i = b.m_msw;
+
+ while (a_i >= a.m_lsw && b_i >= b.m_lsw) {
+ a_word = a.m_mant[a_i];
+ b_word = b.m_mant[b_i];
+ if (a_word > b_word)
+ return 1;
+ if (a_word < b_word)
+ return -1;
+ --a_i;
+ --b_i;
+ }
+
+ bool a_zero = true;
+ while (a_i >= a.m_lsw) {
+ a_zero = a_zero && (a.m_mant[a_i] == 0);
+ --a_i;
+ }
+
+ bool b_zero = true;
+ while (b_i >= b.m_lsw) {
+ b_zero = b_zero && (b.m_mant[b_i] == 0);
+ --b_i;
+ }
+
+ // assertion: a_zero || b_zero
+
+ if (!a_zero && b_zero)
+ return 1;
+
+ if (a_zero && !b_zero)
+ return -1;
+
+ return 0;
+}
+
+// ----------------------------------------------------------------------------
+// FRIEND FUNCTION : cmp_scfx_rep
+//
+// Compares the values of two scfx_reps, including the special cases.
+// ----------------------------------------------------------------------------
+
+int
+cmp_scfx_rep(const scfx_rep &a, const scfx_rep &b)
+{
+ // handle special cases
+
+ if (a.is_nan() || b.is_nan()) {
+ return 2;
+ }
+
+ if (a.is_inf() || b.is_inf()) {
+ if (a.is_inf()) {
+ if (!a.is_neg()) {
+ if (b.is_inf() && !b.is_neg()) {
+ return 0;
+ } else {
+ return 1;
+ }
+ } else {
+ if (b.is_inf() && b.is_neg()) {
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+ }
+ if (b.is_inf()) {
+ if (!b.is_neg()) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+ }
+
+ if (a.is_zero() && b.is_zero()) {
+ return 0;
+ }
+
+ // compare sign
+ if (a.m_sign != b.m_sign) {
+ return a.m_sign;
+ }
+
+ return (a.m_sign * compare_abs(a, b));
+}
+
+
+// ----------------------------------------------------------------------------
+// PRIVATE METHOD : quantization
+//
+// Performs destructive quantization.
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::quantization(const scfx_params &params, bool &q_flag)
+{
+ scfx_index x = calc_indices(params.iwl() - params.wl());
+
+ if (x.wi() < 0)
+ return;
+
+ if (x.wi() >= size())
+ resize_to(x.wi() + 1, 1);
+
+ bool qb = q_bit(x);
+ bool qz = q_zero(x);
+
+ q_flag = (qb || ! qz);
+
+ if (q_flag) {
+ switch (params.q_mode()) {
+ case SC_TRN: // truncation
+ {
+ if (is_neg())
+ q_incr(x);
+ break;
+ }
+ case SC_RND: // rounding to plus infinity
+ {
+ if (!is_neg()) {
+ if (qb)
+ q_incr(x);
+ } else {
+ if (qb && !qz)
+ q_incr(x);
+ }
+ break;
+ }
+ case SC_TRN_ZERO: // truncation to zero
+ {
+ break;
+ }
+ case SC_RND_INF: // rounding to infinity
+ {
+ if (qb)
+ q_incr(x);
+ break;
+ }
+ case SC_RND_CONV: // convergent rounding
+ {
+ if ((qb && !qz) || (qb && qz && q_odd(x)))
+ q_incr(x);
+ break;
+ }
+ case SC_RND_ZERO: // rounding to zero
+ {
+ if (qb && !qz)
+ q_incr(x);
+ break;
+ }
+ case SC_RND_MIN_INF: // rounding to minus infinity
+ {
+ if (!is_neg()) {
+ if (qb && !qz)
+ q_incr(x);
+ } else {
+ if (qb)
+ q_incr(x);
+ }
+ break;
+ }
+ default:
+ ;
+ }
+ q_clear(x);
+
+ find_sw();
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// PRIVATE METHOD : overflow
+//
+// Performs destructive overflow handling.
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::overflow(const scfx_params &params, bool &o_flag)
+{
+ scfx_index x = calc_indices(params.iwl() - 1);
+
+ if (x.wi() >= size())
+ resize_to(x.wi() + 1, 1);
+
+ if (x.wi() < 0) {
+ resize_to(size() - x.wi(), -1);
+ x.wi(0);
+ }
+
+ bool zero_left = o_zero_left(x);
+ bool bit_at = o_bit_at(x);
+ bool zero_right = o_zero_right(x);
+
+ bool under = false;
+ bool over = false;
+
+ sc_enc enc = params.enc();
+
+ if (enc == SC_TC_) {
+ if (is_neg()) {
+ if (params.o_mode() == SC_SAT_SYM)
+ under = (!zero_left || bit_at);
+ else
+ under = (!zero_left || (zero_left && bit_at && ! zero_right));
+ } else {
+ over = (! zero_left || bit_at);
+ }
+ } else {
+ if (is_neg())
+ under = (!is_zero());
+ else
+ over = (!zero_left);
+ }
+
+ o_flag = (under || over);
+
+ if (o_flag) {
+ scfx_index x2 = calc_indices(params.iwl() - params.wl());
+
+ if (x2.wi() < 0) {
+ resize_to(size() - x2.wi(), -1);
+ x.wi(x.wi() - x2.wi());
+ x2.wi(0);
+ }
+
+ switch (params.o_mode()) {
+ case SC_WRAP: // wrap-around
+ {
+ int n_bits = params.n_bits();
+
+ if (n_bits == 0) {
+ // wrap-around all 'wl' bits
+ toggle_tc();
+ o_extend(x, enc);
+ toggle_tc();
+ } else if (n_bits < params.wl()) {
+ scfx_index x3 = calc_indices(params.iwl() - 1 - n_bits);
+
+ // wrap-around least significant 'wl - n_bits' bits;
+ // saturate most significant 'n_bits' bits
+ toggle_tc();
+ o_set(x, x3, enc, under);
+ o_extend(x, enc);
+ toggle_tc();
+ } else {
+ // saturate all 'wl' bits
+ if (under)
+ o_set_low(x, enc);
+ else
+ o_set_high(x, x2, enc);
+ }
+ break;
+ }
+ case SC_SAT: // saturation
+ {
+ if (under)
+ o_set_low(x, enc);
+ else
+ o_set_high(x, x2, enc);
+ break;
+ }
+ case SC_SAT_SYM: // symmetrical saturation
+ {
+ if (under) {
+ if (enc == SC_TC_)
+ o_set_high(x, x2, SC_TC_, -1);
+ else
+ o_set_low(x, SC_US_);
+ } else {
+ o_set_high(x, x2, enc);
+ }
+ break;
+ }
+ case SC_SAT_ZERO: // saturation to zero
+ {
+ set_zero();
+ break;
+ }
+ case SC_WRAP_SM: // sign magnitude wrap-around
+ {
+ SC_ERROR_IF_(enc == SC_US_,
+ "SC_WRAP_SM not defined for unsigned numbers");
+
+ int n_bits = params.n_bits();
+
+ if (n_bits == 0) {
+ scfx_index x4 = calc_indices(params.iwl());
+
+ if (x4.wi() >= size())
+ resize_to(x4.wi() + 1, 1);
+
+ toggle_tc();
+ if (o_bit_at(x4) != o_bit_at(x))
+ o_invert(x2);
+ o_extend(x, SC_TC_);
+ toggle_tc();
+ } else if (n_bits == 1) {
+ toggle_tc();
+ if (is_neg() != o_bit_at(x))
+ o_invert(x2);
+ o_extend(x, SC_TC_);
+ toggle_tc();
+ } else if (n_bits < params.wl()) {
+ scfx_index x3 = calc_indices(params.iwl() - 1 - n_bits);
+ scfx_index x4 = calc_indices(params.iwl() - n_bits);
+
+ // wrap-around least significant 'wl - n_bits' bits;
+ // saturate most significant 'n_bits' bits
+ toggle_tc();
+ if (is_neg() == o_bit_at(x4))
+ o_invert(x2);
+ o_set(x, x3, SC_TC_, under);
+ o_extend(x, SC_TC_);
+ toggle_tc();
+ } else {
+ if (under)
+ o_set_low(x, SC_TC_);
+ else
+ o_set_high(x, x2, SC_TC_);
+ }
+ break;
+ }
+ default:
+ ;
+ }
+
+ find_sw();
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// PUBLIC METHOD : cast
+//
+// Performs a destructive cast operation on a scfx_rep.
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::cast(const scfx_params &params, bool &q_flag, bool &o_flag)
+{
+ q_flag = false;
+ o_flag = false;
+
+ // check for special cases
+ if (is_zero()) {
+ if (is_neg())
+ m_sign = 1;
+ return;
+ }
+
+ // perform casting
+ quantization(params, q_flag);
+ overflow(params, o_flag);
+
+ // check for special case: -0
+ if (is_zero() && is_neg())
+ m_sign = 1;
+}
+
+
+// ----------------------------------------------------------------------------
+// make sure, the two mantissas are aligned
+// ----------------------------------------------------------------------------
+
+void
+align(const scfx_rep &lhs, const scfx_rep &rhs, int &new_wp,
+ int &len_mant, scfx_mant_ref &lhs_mant, scfx_mant_ref &rhs_mant)
+{
+ bool need_lhs = true;
+ bool need_rhs = true;
+
+ if (lhs.m_wp != rhs.m_wp || lhs.size() != rhs.size()) {
+ int lower_bound_lhs = lhs.m_lsw - lhs.m_wp;
+ int upper_bound_lhs = lhs.m_msw - lhs.m_wp;
+ int lower_bound_rhs = rhs.m_lsw - rhs.m_wp;
+ int upper_bound_rhs = rhs.m_msw - rhs.m_wp;
+
+ int lower_bound = sc_min(lower_bound_lhs, lower_bound_rhs);
+ int upper_bound = sc_max(upper_bound_lhs, upper_bound_rhs);
+
+ new_wp = -lower_bound;
+ len_mant = sc_max(min_mant, upper_bound - lower_bound + 1);
+
+ if (new_wp != lhs.m_wp || len_mant != lhs.size()) {
+ lhs_mant = lhs.resize(len_mant, new_wp);
+ need_lhs = false;
+ }
+
+ if (new_wp != rhs.m_wp || len_mant != rhs.size()) {
+ rhs_mant = rhs.resize(len_mant, new_wp);
+ need_rhs = false;
+ }
+ }
+
+ if (need_lhs) {
+ lhs_mant = lhs.m_mant;
+ }
+
+ if (need_rhs) {
+ rhs_mant = rhs.m_mant;
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// compare two mantissas
+// ----------------------------------------------------------------------------
+
+int
+compare_msw_ff(const scfx_rep &lhs, const scfx_rep &rhs)
+{
+ // special case: rhs.m_mant[rhs.m_msw + 1] == 1
+ if (rhs.m_msw < rhs.size() - 1 && rhs.m_mant[rhs.m_msw + 1 ] != 0) {
+ return -1;
+ }
+
+ int lhs_size = lhs.m_msw - lhs.m_lsw + 1;
+ int rhs_size = rhs.m_msw - rhs.m_lsw + 1;
+
+ int size = sc_min(lhs_size, rhs_size);
+
+ int lhs_index = lhs.m_msw;
+ int rhs_index = rhs.m_msw;
+
+ int i;
+
+ for (i = 0;
+ i < size && lhs.m_mant[lhs_index] == rhs.m_mant[rhs_index];
+ i++) {
+ lhs_index--;
+ rhs_index--;
+ }
+
+ if (i == size) {
+ if (lhs_size == rhs_size) {
+ return 0;
+ }
+
+ if (lhs_size < rhs_size) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+
+ if (lhs.m_mant[lhs_index] < rhs.m_mant[rhs_index]) {
+ return -1;
+ } else {
+ return 1;
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// divide the mantissa by ten
+// ----------------------------------------------------------------------------
+
+unsigned int
+scfx_rep::divide_by_ten()
+{
+#if defined(SC_BOOST_BIG_ENDIAN)
+ half_word *hw = (half_word *)&m_mant[m_msw];
+#elif defined(SC_BOOST_LITTLE_ENDIAN)
+ half_word *hw = ((half_word *)&m_mant[m_msw]) + 1;
+#endif
+
+ unsigned int remainder = 0;
+
+ word_short ls;
+ ls.l = 0;
+
+#if defined(SC_BOOST_BIG_ENDIAN)
+ for (int i = 0, end = (m_msw - m_wp + 1) * 2; i < end; i++) {
+#elif defined(SC_BOOST_LITTLE_ENDIAN)
+ for (int i = 0, end = -(m_msw - m_wp + 1) * 2; i > end; i--) {
+#endif
+ ls.s.u = static_cast<half_word>(remainder);
+ ls.s.l = hw[i];
+ remainder = ls.l % 10;
+ ls.l /= 10;
+ hw[i] = ls.s.l;
+ }
+
+ return remainder;
+}
+
+
+// ----------------------------------------------------------------------------
+// multiply the mantissa by ten
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::multiply_by_ten()
+{
+ int size = m_mant.size() + 1;
+
+ scfx_mant mant8(size);
+ scfx_mant mant2(size);
+
+ size--;
+
+ mant8[size] = (m_mant[size - 1] >> (bits_in_word - 3));
+ mant2[size] = (m_mant[size - 1] >> (bits_in_word - 1));
+
+ while (--size) {
+ mant8[size] = (m_mant[size] << 3) |
+ (m_mant[size - 1] >> (bits_in_word - 3));
+ mant2[size] = (m_mant[size] << 1) |
+ (m_mant[size - 1] >> (bits_in_word - 1));
+ }
+
+ mant8[0] = (m_mant[0] << 3);
+ mant2[0] = (m_mant[0] << 1);
+
+ add_mants(m_mant.size(), m_mant, mant8, mant2);
+}
+
+
+// ----------------------------------------------------------------------------
+// normalize
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::normalize(int exponent)
+{
+ int shift = exponent % bits_in_word;
+ if (shift < 0) {
+ shift += bits_in_word;
+ }
+
+ if (shift) {
+ shift_left(shift);
+ }
+
+ find_sw();
+
+ m_wp = (shift - exponent) / bits_in_word;
+}
+
+
+// ----------------------------------------------------------------------------
+// return a new mantissa that is aligned and resized
+// ----------------------------------------------------------------------------
+
+scfx_mant *
+scfx_rep::resize(int new_size, int new_wp) const
+{
+ scfx_mant *result = new scfx_mant(new_size);
+
+ result->clear();
+
+ int shift = new_wp - m_wp;
+
+ for (int j = m_lsw; j <= m_msw; j++) {
+ (*result)[j + shift] = m_mant[j];
+ }
+
+ return result;
+}
+
+
+// ----------------------------------------------------------------------------
+// set a single bit
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::set_bin(int i)
+{
+ m_mant[i >> 5] |= 1 << (i & 31);
+}
+
+
+// ----------------------------------------------------------------------------
+// set three bits
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::set_oct(int i, int n)
+{
+ if (n & 1) {
+ m_mant[i >> 5] |= 1 << (i & 31);
+ }
+ i++;
+ if (n & 2) {
+ m_mant[i >> 5] |= 1 << (i & 31);
+ }
+ i++;
+ if (n & 4) {
+ m_mant[i >> 5] |= 1 << (i & 31);
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// set four bits
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::set_hex(int i, int n)
+{
+ if (n & 1) {
+ m_mant[i >> 5] |= 1 << (i & 31);
+ }
+ i++;
+ if (n & 2) {
+ m_mant[i >> 5] |= 1 << (i & 31);
+ }
+ i++;
+ if (n & 4) {
+ m_mant[i >> 5] |= 1 << (i & 31);
+ }
+ i++;
+ if (n & 8) {
+ m_mant[i >> 5] |= 1 << (i & 31);
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// PRIVATE METHOD : shift_left
+//
+// Shifts a scfx_rep to the left by a MAXIMUM of bits_in_word - 1 bits.
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::shift_left(int n)
+{
+ if (n != 0) {
+ int shift_left = n;
+ int shift_right = bits_in_word - n;
+
+ SC_ASSERT_(!(m_mant[size() - 1] >> shift_right),
+ "shift_left overflow");
+
+ for (int i = size() - 1; i > 0; i--) {
+ m_mant[i] = (m_mant[i] << shift_left) |
+ (m_mant[i - 1] >> shift_right);
+ }
+ m_mant[0] <<= shift_left;
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// PRIVATE METHOD : shift_right
+//
+// Shifts a scfx_rep to the right by a MAXIMUM of bits_in_word - 1 bits.
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::shift_right(int n)
+{
+ if (n != 0) {
+ int shift_left = bits_in_word - n;
+ int shift_right = n;
+
+ SC_ASSERT_(!(m_mant[0] << shift_left), "shift_right overflow");
+
+ for (int i = 0; i < size() - 1; i++) {
+ m_mant[i] = (m_mant[i] >> shift_right) |
+ (m_mant[i + 1] << shift_left);
+ }
+ m_mant[size() - 1] >>= shift_right;
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : get_bit
+//
+// Tests a bit, in two's complement.
+// ----------------------------------------------------------------------------
+
+bool
+scfx_rep::get_bit(int i) const
+{
+ if (!is_normal())
+ return false;
+
+ scfx_index x = calc_indices(i);
+
+ if (x.wi() >= size())
+ return is_neg();
+
+ if (x.wi() < 0)
+ return false;
+
+ const_cast<scfx_rep*>(this)->toggle_tc();
+
+ bool result = (m_mant[x.wi()] & (1 << x.bi())) != 0;
+
+ const_cast<scfx_rep *>(this)->toggle_tc();
+
+ return result;
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : set
+//
+// Sets a bit, in two's complement, between iwl-1 and -fwl.
+// ----------------------------------------------------------------------------
+
+bool
+scfx_rep::set(int i, const scfx_params &params)
+{
+ if (!is_normal())
+ return false;
+
+ scfx_index x = calc_indices(i);
+
+ if (x.wi() >= size()) {
+ if (is_neg())
+ return true;
+ else
+ resize_to(x.wi() + 1, 1);
+ } else if (x.wi() < 0) {
+ resize_to(size() - x.wi(), -1);
+ x.wi(0);
+ }
+
+ toggle_tc();
+
+ m_mant[x.wi()] |= 1 << x.bi();
+
+ if (i == params.iwl() - 1)
+ o_extend(x, params.enc()); // sign extension
+
+ toggle_tc();
+
+ find_sw();
+
+ return true;
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : clear
+//
+// Clears a bit, in two's complement, between iwl-1 and -fwl.
+// ----------------------------------------------------------------------------
+
+bool
+scfx_rep::clear(int i, const scfx_params &params)
+{
+ if (!is_normal())
+ return false;
+
+ scfx_index x = calc_indices(i);
+
+ if (x.wi() >= size()) {
+ if (!is_neg())
+ return true;
+ else
+ resize_to(x.wi() + 1, 1);
+ } else if (x.wi() < 0) {
+ return true;
+ }
+
+ toggle_tc();
+
+ m_mant[x.wi()] &= ~(1 << x.bi());
+
+ if (i == params.iwl() - 1)
+ o_extend(x, params.enc()); // sign extension
+
+ toggle_tc();
+
+ find_sw();
+
+ return true;
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : get_slice
+// ----------------------------------------------------------------------------
+
+bool
+scfx_rep::get_slice(int i, int j, const scfx_params &, sc_bv_base &bv) const
+{
+ if (is_nan() || is_inf())
+ return false;
+
+ // get the bits
+
+ int l = j;
+ for (int k = 0; k < bv.length(); ++k) {
+ bv[k] = get_bit(l);
+
+ if (i >= j)
+ ++l;
+ else
+ --l;
+ }
+
+ return true;
+}
+
+bool
+scfx_rep::set_slice(int i, int j, const scfx_params &params,
+ const sc_bv_base &bv)
+{
+ if (is_nan() || is_inf())
+ return false;
+
+ // set the bits
+ int l = j;
+ for (int k = 0; k < bv.length(); ++k) {
+ if (bv[k].to_bool())
+ set(l, params);
+ else
+ clear(l, params);
+
+ if (i >= j)
+ ++l;
+ else
+ --l;
+ }
+
+ return true;
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : print
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::print(::std::ostream &os) const
+{
+ os << to_string(SC_DEC, -1, SC_E);
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : dump
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::dump(::std::ostream &os) const
+{
+ os << "scfx_rep" << ::std::endl;
+ os << "(" << ::std::endl;
+
+ os << "mant =" << ::std::endl;
+ for (int i = size() - 1; i >= 0; i--) {
+ char buf[BUFSIZ];
+ std::sprintf(buf, " %d: %10u (%8x)", i,
+ (int)m_mant[i], (int)m_mant[i]);
+ os << buf << ::std::endl;
+ }
+
+ os << "wp = " << m_wp << ::std::endl;
+ os << "sign = " << m_sign << ::std::endl;
+
+ os << "state = ";
+ switch (m_state) {
+ case normal:
+ os << "normal";
+ break;
+ case infinity:
+ os << "infinity";
+ break;
+ case not_a_number:
+ os << "not_a_number";
+ break;
+ default:
+ os << "unknown";
+ }
+ os << ::std::endl;
+
+ os << "msw = " << m_msw << ::std::endl;
+ os << "lsw = " << m_lsw << ::std::endl;
+
+ os << ")" << ::std::endl;
+}
+
+
+// ----------------------------------------------------------------------------
+// METHOD : get_type
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::get_type(int &wl, int &iwl, sc_enc &enc) const
+{
+ if (is_nan() || is_inf()) {
+ wl = 0;
+ iwl = 0;
+ enc = SC_TC_;
+ return;
+ }
+
+ if (is_zero()) {
+ wl = 1;
+ iwl = 1;
+ enc = SC_US_;
+ return;
+ }
+
+ int msb = (m_msw - m_wp) * bits_in_word +
+ scfx_find_msb(m_mant[ m_msw ]) + 1;
+ while (get_bit(msb) == get_bit(msb - 1)) {
+ --msb;
+ }
+
+ int lsb = (m_lsw - m_wp) * bits_in_word +
+ scfx_find_lsb(m_mant[m_lsw]);
+
+ if (is_neg()) {
+ wl = msb - lsb + 1;
+ iwl = msb + 1;
+ enc = SC_TC_;
+ } else {
+ wl = msb - lsb;
+ iwl = msb;
+ enc = SC_US_;
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// PRIVATE METHOD : round
+//
+// Performs convergent rounding (rounding to even) as in floating-point.
+// ----------------------------------------------------------------------------
+
+void
+scfx_rep::round(int wl)
+{
+ // check for special cases
+
+ if (is_nan() || is_inf() || is_zero())
+ return;
+
+ // estimate effective wordlength and compare
+ int wl_effective;
+ wl_effective = (m_msw - m_lsw + 1) * bits_in_word;
+ if (wl_effective <= wl)
+ return;
+
+ // calculate effective wordlength and compare
+ int msb = scfx_find_msb(m_mant[m_msw]);
+ int lsb = scfx_find_lsb(m_mant[m_lsw]);
+ wl_effective = (m_msw * bits_in_word + msb) -
+ (m_lsw * bits_in_word + lsb) + 1;
+ if (wl_effective <= wl)
+ return;
+
+ // perform rounding
+ int wi = m_msw - (wl - 1) / bits_in_word;
+ int bi = msb - (wl - 1) % bits_in_word;
+ if (bi < 0) {
+ --wi;
+ bi += bits_in_word;
+ }
+
+ scfx_index x(wi, bi);
+
+ if ((q_bit(x) && ! q_zero(x)) || (q_bit(x) && q_zero(x) && q_odd(x))) {
+ q_incr(x);
+ }
+ q_clear(x);
+
+ find_sw();
+
+ m_r_flag = true;
+}
+
+} // namespace sc_dt
diff --git a/src/systemc/dt/fx/scfx_utils.cc b/src/systemc/dt/fx/scfx_utils.cc
new file mode 100644
index 000000000..844e15df6
--- /dev/null
+++ b/src/systemc/dt/fx/scfx_utils.cc
@@ -0,0 +1,162 @@
+/*****************************************************************************
+
+ 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_utils.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: scfx_utils.cpp,v $
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:58 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include "systemc/ext/dt/fx/scfx_utils.hh"
+
+namespace sc_dt
+{
+
+void
+scfx_tc2csd(scfx_string &s, int w_prefix)
+{
+ if (w_prefix != 0) {
+ SC_ASSERT_(s[0] == '0' && s[1] == 'c' &&
+ s[2] == 's' && s[3] == 'd', "invalid prefix");
+ }
+
+ scfx_string csd;
+
+ // copy bits from 's' into 'csd'; skip prefix, point, and exponent
+ int i = 0;
+ int j = (w_prefix != 0 ? 4 : 0);
+ while (s[j]) {
+ if (s[j] == '0' || s[j] == '1')
+ csd[i ++] = s[j];
+ else if (s[j] != '.')
+ break;
+ ++j;
+ }
+ csd[i] = '\0';
+
+ // convert 'csd' from two's complement to csd
+ --i;
+ while (i >= 0) {
+ if (csd[i] == '0') {
+ --i;
+ } else {
+ if (i > 0 && csd[i - 1] == '0') {
+ --i;
+ } else if (i == 0) {
+ csd[i--] = '-';
+ } else {
+ csd[i--] = '-';
+ while (i >= 0 && csd[i] == '1')
+ csd[i--] = '0';
+ if (i > 0)
+ csd[i] = '1';
+ else if (i == 0)
+ csd[i--] = '1';
+ }
+ }
+ }
+
+ // copy bits from 'csd' back into 's'
+ i = 0;
+ j = (w_prefix != 0 ? 4 : 0);
+ while (csd[i]) {
+ if (s[j] == '.')
+ ++j;
+ s[j++] = csd[i++];
+ }
+}
+
+
+void
+scfx_csd2tc(scfx_string &csd)
+{
+ SC_ASSERT_(csd[0] == '0' && csd[1] == 'c' &&
+ csd[2] == 's' && csd[3] == 'd', "invalid prefix");
+
+ scfx_string s;
+
+ // copy bits from 'csd' into 's'; skip prefix, point, and exponent
+ int i = 0;
+ s[i++] = '0';
+ int j = 4;
+ while (csd[j]) {
+ if (csd[j] == '-' || csd[j] == '0' || csd[j] == '1')
+ s[i++] = csd[j];
+ else if (csd[j] != '.')
+ break;
+ ++j;
+ }
+ s[i] = '\0';
+
+ // convert 's' from csd to two's complement
+ int len = i;
+ i = 1;
+ while (i < len) {
+ while (i < len && s[i] != '-')
+ i++;
+ if (i < len) {
+ j = i++;
+ s[j--] = '1';
+ while (j >= 0 && s[j] == '0')
+ s[j--] = '1';
+ if (j >= 0)
+ s[j] = '0';
+ }
+ }
+
+ // copy bits from 's' back into 'csd'
+ j = csd.length();
+ csd[j + 1] = '\0';
+ while (j > 4) {
+ csd[j] = csd[j - 1];
+ --j;
+ }
+
+ i = 0;
+ j = 4;
+ while (s[i]) {
+ if (csd[j] == '.')
+ ++j;
+ csd[j++] = s[i++];
+ }
+}
+
+} // namespace sc_dt