summaryrefslogtreecommitdiff
path: root/src/systemc/dt/fx/sc_fxnum.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemc/dt/fx/sc_fxnum.cc')
-rw-r--r--src/systemc/dt/fx/sc_fxnum.cc867
1 files changed, 867 insertions, 0 deletions
diff --git a/src/systemc/dt/fx/sc_fxnum.cc b/src/systemc/dt/fx/sc_fxnum.cc
new file mode 100644
index 000000000..f47b4d342
--- /dev/null
+++ b/src/systemc/dt/fx/sc_fxnum.cc
@@ -0,0 +1,867 @@
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_fxnum.cpp -
+
+ Original Author: Martin Janssen, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_fxnum.cpp,v $
+// Revision 1.3 2011/01/19 18:57:40 acg
+// Andy Goodrich: changes for IEEE_1666_2011.
+//
+// Revision 1.2 2010/12/07 20:09:08 acg
+// Andy Goodrich: Philipp Hartmann's constructor disambiguation fix
+//
+// Revision 1.1.1.1 2006/12/15 20:20:04 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:53:57 acg
+// Andy Goodrich: added $Log command so that CVS comments are reproduced in
+// the source.
+//
+
+#include <cmath>
+
+#include "systemc/ext/dt/fx/sc_fxnum.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_bitref
+//
+// Proxy class for bit-selection in class sc_fxnum, behaves like sc_bit.
+// ----------------------------------------------------------------------------
+
+bool sc_fxnum_bitref::get() const { return m_num.get_bit(m_idx); }
+void sc_fxnum_bitref::set(bool high) { m_num.set_bit(m_idx, high); }
+
+// print or dump content
+void sc_fxnum_bitref::print(::std::ostream &os) const { os << get(); }
+
+void
+sc_fxnum_bitref::scan(::std::istream &is)
+{
+ bool b;
+ is >> b;
+ *this = b;
+}
+
+void
+sc_fxnum_bitref::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum_bitref" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "num = ";
+ m_num.dump(os);
+ os << "idx = " << m_idx << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_fast_bitref
+//
+// Proxy class for bit-selection in class sc_fxnum_fast, behaves like sc_bit.
+// ----------------------------------------------------------------------------
+
+bool sc_fxnum_fast_bitref::get() const { return m_num.get_bit(m_idx); }
+void sc_fxnum_fast_bitref::set(bool high) { m_num.set_bit(m_idx, high); }
+
+// print or dump content
+void sc_fxnum_fast_bitref::print(::std::ostream &os) const { os << get(); }
+
+void
+sc_fxnum_fast_bitref::scan(::std::istream &is)
+{
+ bool b;
+ is >> b;
+ *this = b;
+}
+
+void
+sc_fxnum_fast_bitref::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum_fast_bitref" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "num = ";
+ m_num.dump(os);
+ os << "idx = " << m_idx << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_subref
+//
+// Proxy class for part-selection in class sc_fxnum,
+// behaves like sc_bv_base.
+// ----------------------------------------------------------------------------
+
+bool
+sc_fxnum_subref::get() const
+{
+ return m_num.get_slice(m_from, m_to, m_bv);
+}
+
+bool
+sc_fxnum_subref::set()
+{
+ return m_num.set_slice(m_from, m_to, m_bv);
+}
+
+// print or dump content
+void
+sc_fxnum_subref::print(::std::ostream &os) const
+{
+ get();
+ m_bv.print(os);
+}
+
+void
+sc_fxnum_subref::scan(::std::istream &is)
+{
+ m_bv.scan(is);
+ set();
+}
+
+void
+sc_fxnum_subref::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum_subref" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "num = ";
+ m_num.dump(os);
+ os << "from = " << m_from << ::std::endl;
+ os << "to = " << m_to << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_fast_subref
+//
+// Proxy class for part-selection in class sc_fxnum_fast,
+// behaves like sc_bv_base.
+// ----------------------------------------------------------------------------
+
+bool
+sc_fxnum_fast_subref::get() const
+{
+ return m_num.get_slice(m_from, m_to, m_bv);
+}
+
+bool
+sc_fxnum_fast_subref::set()
+{
+ return m_num.set_slice(m_from, m_to, m_bv);
+}
+
+// print or dump content
+void
+sc_fxnum_fast_subref::print(::std::ostream &os) const
+{
+ get();
+ m_bv.print(os);
+}
+
+void
+sc_fxnum_fast_subref::scan(::std::istream &is)
+{
+ m_bv.scan(is);
+ set();
+}
+
+void
+sc_fxnum_fast_subref::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum_fast_subref" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "num = ";
+ m_num.dump(os);
+ os << "from = " << m_from << ::std::endl;
+ os << "to = " << m_to << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum
+//
+// Base class for the fixed-point types; arbitrary precision.
+// ----------------------------------------------------------------------------
+
+// explicit conversion to character string
+
+const std::string
+sc_fxnum::to_string() const
+{
+ return std::string(m_rep->to_string(SC_DEC, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_string(sc_numrep numrep) const
+{
+ return std::string(m_rep->to_string(numrep, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_string(sc_numrep numrep, bool w_prefix) const
+{
+ return std::string(m_rep->to_string(numrep, (w_prefix ? 1 : 0),
+ SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_string(sc_fmt fmt) const
+{
+ return std::string(m_rep->to_string(SC_DEC, -1, fmt, &m_params));
+}
+
+const std::string
+sc_fxnum::to_string(sc_numrep numrep, sc_fmt fmt) const
+{
+ return std::string(m_rep->to_string(numrep, -1, fmt, &m_params));
+}
+
+const std::string
+sc_fxnum::to_string(sc_numrep numrep, bool w_prefix, sc_fmt fmt) const
+{
+ return std::string(m_rep->to_string(numrep, (w_prefix ? 1 : 0),
+ fmt, &m_params));
+}
+
+
+const std::string
+sc_fxnum::to_dec() const
+{
+ return std::string(m_rep->to_string(SC_DEC, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_bin() const
+{
+ return std::string(m_rep->to_string(SC_BIN, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_oct() const
+{
+ return std::string(m_rep->to_string(SC_OCT, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum::to_hex() const
+{
+ return std::string(m_rep->to_string(SC_HEX, -1, SC_F, &m_params));
+}
+
+
+// print or dump content
+void
+sc_fxnum::print(::std::ostream &os) const
+{
+ os << m_rep->to_string(SC_DEC, -1, SC_F, &m_params);
+}
+
+void
+sc_fxnum::scan(::std::istream &is)
+{
+ std::string s;
+ is >> s;
+ *this = s.c_str();
+}
+
+void
+sc_fxnum::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "rep = ";
+ m_rep->dump(os);
+ os << "params = ";
+ m_params.dump(os);
+ os << "q_flag = " << m_q_flag << ::std::endl;
+ os << "o_flag = " << m_o_flag << ::std::endl;
+ // TO BE COMPLETED
+ // os << "observer = ";
+ // if (m_observer != 0)
+ // m_observer->dump(os);
+ // else
+ // os << "0" << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+
+sc_fxnum_observer *
+sc_fxnum::lock_observer() const
+{
+ SC_ASSERT_(m_observer != 0, "lock observer failed");
+ sc_fxnum_observer * tmp = m_observer;
+ m_observer = 0;
+ return tmp;
+}
+
+void
+sc_fxnum::unlock_observer(sc_fxnum_observer *observer_) const
+{
+ SC_ASSERT_(observer_ != 0, "unlock observer failed");
+ m_observer = observer_;
+}
+
+
+// ----------------------------------------------------------------------------
+// CLASS : sc_fxnum_fast
+//
+// Base class for the fixed-point types; limited precision.
+// ----------------------------------------------------------------------------
+
+static void
+quantization(double &c, const scfx_params &params, bool &q_flag)
+{
+ int fwl = params.wl() - params.iwl();
+ double scale = scfx_pow2(fwl);
+ double val = scale * c;
+ double int_part;
+ double frac_part = modf(val, &int_part);
+
+ q_flag = (frac_part != 0.0);
+
+ if (q_flag) {
+ val = int_part;
+
+ switch (params.q_mode()) {
+ case SC_TRN: // truncation
+ {
+ if (c < 0.0)
+ val -= 1.0;
+ break;
+ }
+ case SC_RND: // rounding to plus infinity
+ {
+ if (frac_part >= 0.5)
+ val += 1.0;
+ else if (frac_part < -0.5)
+ val -= 1.0;
+ break;
+ }
+ case SC_TRN_ZERO: // truncation to zero
+ {
+ break;
+ }
+ case SC_RND_INF: // rounding to infinity
+ {
+ if (frac_part >= 0.5)
+ val += 1.0;
+ else if (frac_part <= -0.5)
+ val -= 1.0;
+ break;
+ }
+ case SC_RND_CONV: // convergent rounding
+ {
+ if (frac_part > 0.5 ||
+ (frac_part == 0.5 && fmod(int_part, 2.0) != 0.0)) {
+ val += 1.0;
+ } else if (frac_part < -0.5 ||
+ (frac_part == -0.5 && fmod(int_part, 2.0) != 0.0)) {
+ val -= 1.0;
+ }
+ break;
+ }
+ case SC_RND_ZERO: // rounding to zero
+ {
+ if (frac_part > 0.5)
+ val += 1.0;
+ else if (frac_part < -0.5)
+ val -= 1.0;
+ break;
+ }
+ case SC_RND_MIN_INF: // rounding to minus infinity
+ {
+ if (frac_part > 0.5)
+ val += 1.0;
+ else if (frac_part <= -0.5)
+ val -= 1.0;
+ break;
+ }
+ default:
+ ;
+ }
+ }
+
+ val /= scale;
+ c = val;
+}
+
+static void
+overflow(double &c, const scfx_params &params, bool &o_flag)
+{
+ int iwl = params.iwl();
+ int fwl = params.wl() - iwl;
+ double full_circle = scfx_pow2(iwl);
+ double resolution = scfx_pow2(-fwl);
+ double low, high;
+ if (params.enc() == SC_TC_) {
+ high = full_circle / 2.0 - resolution;
+ if (params.o_mode() == SC_SAT_SYM)
+ low = - high;
+ else
+ low = - full_circle / 2.0;
+ } else {
+ low = 0.0;
+ high = full_circle - resolution;
+ }
+ double val = c;
+ sc_fxval_fast c2(c);
+
+ bool under = (val < low);
+ bool over = (val > high);
+
+ o_flag = (under || over);
+
+ if (o_flag) {
+ switch (params.o_mode()) {
+ case SC_WRAP: // wrap-around
+ {
+ int n_bits = params.n_bits();
+
+ if (n_bits == 0) {
+ // wrap-around all 'wl' bits
+ val -= floor(val / full_circle) * full_circle;
+ if (val > high)
+ val -= full_circle;
+ } else if (n_bits < params.wl()) {
+ double X = scfx_pow2(iwl - n_bits);
+
+ // wrap-around least significant 'wl - n_bits' bits
+ val -= floor(val / X) * X;
+ if (val > (X - resolution))
+ val -= X;
+
+ // saturate most significant 'n_bits' bits
+ if (under) {
+ val += low;
+ } else {
+ if (params.enc() == SC_TC_)
+ val += full_circle / 2.0 - X;
+ else
+ val += full_circle - X;
+ }
+ } else {
+ // saturate all 'wl' bits
+ if (under)
+ val = low;
+ else
+ val = high;
+ }
+ break;
+ }
+ case SC_SAT: // saturation
+ case SC_SAT_SYM: // symmetrical saturation
+ {
+ if (under)
+ val = low;
+ else
+ val = high;
+ break;
+ }
+ case SC_SAT_ZERO: // saturation to zero
+ {
+ val = 0.0;
+ break;
+ }
+ case SC_WRAP_SM: // sign magnitude wrap-around
+ {
+ SC_ERROR_IF_(params.enc() == SC_US_,
+ "SC_WRAP_SM not defined for unsigned numbers");
+
+ int n_bits = params.n_bits();
+
+ if (n_bits == 0) {
+ // invert conditionally
+ if (c2.get_bit(iwl) != c2.get_bit(iwl - 1))
+ val = -val - resolution;
+
+ // wrap-around all 'wl' bits
+ val -= floor(val / full_circle) * full_circle;
+ if (val > high)
+ val -= full_circle;
+ } else if (n_bits == 1) {
+ // invert conditionally
+ if (c2.is_neg() != c2.get_bit(iwl - 1))
+ val = -val - resolution;
+
+ // wrap-around all 'wl' bits
+ val -= floor(val / full_circle) * full_circle;
+ if (val > high)
+ val -= full_circle;
+ } else if (n_bits < params.wl()) {
+ // invert conditionally
+ if (c2.is_neg() == c2.get_bit(iwl - n_bits))
+ val = -val - resolution;
+
+ double X = scfx_pow2(iwl - n_bits);
+
+ // wrap-around least significant 'wl - n_bits' bits
+ val -= floor(val / X) * X;
+ if (val > (X - resolution))
+ val -= X;
+
+ // saturate most significant 'n_bits' bits
+ if (under)
+ val += low;
+ else
+ val += full_circle / 2.0 - X;
+ } else {
+ // saturate all 'wl' bits
+ if (under)
+ val = low;
+ else
+ val = high;
+ }
+ break;
+ }
+ default:
+ ;
+ }
+
+ c = val;
+ }
+}
+
+
+void
+sc_fxnum_fast::cast()
+{
+ scfx_ieee_double id(m_val);
+ SC_ERROR_IF_(id.is_nan() || id.is_inf(), "invalid fixed-point value");
+
+ if (m_params.cast_switch() == SC_ON) {
+ m_q_flag = false;
+ m_o_flag = false;
+
+ // check for special cases
+
+ if (id.is_zero()) {
+ if (id.negative() != 0)
+ m_val = -m_val;
+ return;
+ }
+
+ // perform casting
+ sc_dt::quantization(m_val, m_params, m_q_flag);
+ sc_dt::overflow(m_val, m_params, m_o_flag);
+
+ // check for special case: -0
+ id = m_val;
+ if (id.is_zero() && id.negative() != 0) {
+ m_val = -m_val;
+ }
+
+ // check for special case: NaN of Inf
+ if (id.is_nan() || id.is_inf()) {
+ m_val = 0.0;
+ }
+ }
+}
+
+
+// defined in sc_fxval.cpp;
+extern const char* to_string(const scfx_ieee_double &, sc_numrep, int, sc_fmt,
+ const scfx_params * =0);
+
+
+// explicit conversion to character string
+
+const std::string
+sc_fxnum_fast::to_string() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_DEC, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_string(sc_numrep numrep) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_string(sc_numrep numrep, bool w_prefix) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, (w_prefix ? 1 : 0),
+ SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_string(sc_fmt fmt) const
+{
+ return std::string(sc_dt::to_string(m_val, SC_DEC, -1, fmt, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_string(sc_numrep numrep, sc_fmt fmt) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, -1, fmt, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_string(sc_numrep numrep, bool w_prefix, sc_fmt fmt) const
+{
+ return std::string(sc_dt::to_string(m_val, numrep, (w_prefix ? 1 : 0),
+ fmt, &m_params));
+}
+
+
+const std::string
+sc_fxnum_fast::to_dec() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_DEC, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_bin() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_BIN, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_oct() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_OCT, -1, SC_F, &m_params));
+}
+
+const std::string
+sc_fxnum_fast::to_hex() const
+{
+ return std::string(sc_dt::to_string(m_val, SC_HEX, -1, SC_F, &m_params));
+}
+
+// print or dump content
+void
+sc_fxnum_fast::print(::std::ostream &os) const
+{
+ os << sc_dt::to_string(m_val, SC_DEC, -1, SC_F, &m_params);
+}
+
+void
+sc_fxnum_fast::scan(::std::istream &is)
+{
+ std::string s;
+ is >> s;
+ *this = s.c_str();
+}
+
+void
+sc_fxnum_fast::dump(::std::ostream &os) const
+{
+ os << "sc_fxnum_fast" << ::std::endl;
+ os << "(" << ::std::endl;
+ os << "val = " << m_val << ::std::endl;
+ os << "params = ";
+ m_params.dump(os);
+ os << "q_flag = " << m_q_flag << ::std::endl;
+ os << "o_flag = " << m_o_flag << ::std::endl;
+ // TO BE COMPLETED
+ // os << "observer = ";
+ // if (m_observer != 0)
+ // m_observer->dump(os);
+ // else
+ // os << "0" << ::std::endl;
+ os << ")" << ::std::endl;
+}
+
+// internal use only;
+bool
+sc_fxnum_fast::get_bit(int i) const
+{
+ scfx_ieee_double id(m_val);
+ if (id.is_zero() || id.is_nan() || id.is_inf())
+ return false;
+
+ // convert to two's complement
+ unsigned int m0 = id.mantissa0();
+ unsigned int m1 = id.mantissa1();
+
+ if (id.is_normal())
+ m0 += 1U << 20;
+
+ if (id.negative() != 0) {
+ m0 = ~ m0;
+ m1 = ~ m1;
+ unsigned int tmp = m1;
+ m1 += 1U;
+ if (m1 <= tmp)
+ m0 += 1U;
+ }
+
+ // get the right bit
+ int j = i - id.exponent();
+ if ((j += 20) >= 32)
+ return ((m0 & 1U << 31) != 0);
+ else if (j >= 0)
+ return ((m0 & 1U << j) != 0);
+ else if ((j += 32) >= 0)
+ return ((m1 & 1U << j) != 0);
+ else
+ return false;
+}
+
+
+bool
+sc_fxnum_fast::set_bit(int i, bool high)
+{
+ scfx_ieee_double id(m_val);
+ if (id.is_nan() || id.is_inf())
+ return false;
+
+ if (high) {
+ if (get_bit(i))
+ return true;
+
+ if (m_params.enc() == SC_TC_ && i == m_params.iwl() - 1)
+ m_val -= scfx_pow2(i);
+ else
+ m_val += scfx_pow2(i);
+ } else {
+ if (!get_bit(i))
+ return true;
+
+ if (m_params.enc() == SC_TC_ && i == m_params.iwl() - 1)
+ m_val += scfx_pow2(i);
+ else
+ m_val -= scfx_pow2(i);
+ }
+
+ return true;
+}
+
+
+bool
+sc_fxnum_fast::get_slice(int i, int j, sc_bv_base &bv) const
+{
+ scfx_ieee_double id(m_val);
+ if (id.is_nan() || id.is_inf())
+ return false;
+
+ // convert to two's complement
+ unsigned int m0 = id.mantissa0();
+ unsigned int m1 = id.mantissa1();
+
+ if (id.is_normal())
+ m0 += 1U << 20;
+
+ if (id.negative() != 0) {
+ m0 = ~ m0;
+ m1 = ~ m1;
+ unsigned int tmp = m1;
+ m1 += 1U;
+ if (m1 <= tmp)
+ m0 += 1U;
+ }
+
+ // get the bits
+ int l = j;
+ for (int k = 0; k < bv.length(); ++ k) {
+ bool b = false;
+
+ int n = l - id.exponent();
+ if ((n += 20) >= 32)
+ b = ((m0 & 1U << 31) != 0);
+ else if (n >= 0)
+ b = ((m0 & 1U << n) != 0);
+ else if ((n += 32) >= 0)
+ b = ((m1 & 1U << n) != 0);
+
+ bv[k] = b;
+
+ if (i >= j)
+ ++l;
+ else
+ --l;
+ }
+
+ return true;
+}
+
+bool
+sc_fxnum_fast::set_slice(int i, int j, const sc_bv_base &bv)
+{
+ scfx_ieee_double id(m_val);
+ if (id.is_nan() || id.is_inf())
+ return false;
+
+ // set the bits
+ int l = j;
+ for (int k = 0; k < bv.length(); ++k) {
+ if (bv[k].to_bool()) {
+ if (!get_bit(l)) {
+ if (m_params.enc() == SC_TC_ && l == m_params.iwl() - 1)
+ m_val -= scfx_pow2(l);
+ else
+ m_val += scfx_pow2(l);
+ }
+ } else {
+ if (get_bit(l)) {
+ if (m_params.enc() == SC_TC_ && l == m_params.iwl() - 1)
+ m_val += scfx_pow2(l);
+ else
+ m_val -= scfx_pow2(l);
+ }
+ }
+
+ if (i >= j)
+ ++l;
+ else
+ --l;
+ }
+
+ return true;
+}
+
+sc_fxnum_fast_observer *
+sc_fxnum_fast::lock_observer() const
+{
+ SC_ASSERT_(m_observer != 0, "lock observer failed");
+ sc_fxnum_fast_observer *tmp = m_observer;
+ m_observer = 0;
+ return tmp;
+}
+
+void
+sc_fxnum_fast::unlock_observer(sc_fxnum_fast_observer *observer_) const
+{
+ SC_ASSERT_(observer_ != 0, "unlock observer failed");
+ m_observer = observer_;
+}
+
+} // namespace sc_dt