rc_signal.h

Go to the documentation of this file.
00001 // vim:set et sts=4 ts=4 tw=75 sw=4 ai ci cin cino=g0,t0:
00002 /*
00003  * Copyright (C) 2007, Technical Computer Science Group,
00004  *                     University of Bonn
00005  *
00006  * This file is part of the ReChannel library.
00007  *
00008  * The ReChannel library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License as
00010  * published by the Free Software Foundation; either version 2 of the
00011  * License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be
00014  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this library; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
00021  * Boston, MA 02110-1301, USA.
00022  *
00023  * Authors: Andreas Raabe and Armin Felke. Implementation by Armin Felke.
00024  *          {raabe, felke}@cs.uni-bonn.de
00025  */
00037 #ifndef RC_SIGNAL_H_
00038 #define RC_SIGNAL_H_
00039 
00040 #include "ReChannel/components/rc_prim_channel.h"
00041 #include "ReChannel/components/rc_report_ids.h"
00042 #include "ReChannel/core/rc_reset_channel_if.h"
00043 #include "ReChannel/communication/rc_fallback_interface.h"
00044 
00045 namespace ReChannel {
00046 
00047 namespace internals {
00048 namespace signals {
00049 
00050 void report_binding_error(
00051     const sc_object& target, const sc_object& port1,
00052     const sc_object& port2);
00053 
00054 void report_driver_conflict(
00055     const sc_object& target, const sc_object& driver1,
00056     const sc_object& driver2);
00057 
00058 } // namespace internals
00059 } // namespace signals
00060 
00064 template<class T>
00065 class rc_signal_b
00066     : public sc_signal_inout_if<T>,
00067       public rc_prim_channel
00068 {
00069 protected:
00070 
00071 /* constructor */
00072 
00073     explicit rc_signal_b(const char* name_)
00074         : rc_prim_channel(name_),
00075           m_current_value(rc_undefined_value<T>()),
00076           m_delta(~0), m_new_value(m_current_value),
00077           m_reset_value(m_current_value),
00078           m_notify_value_changed_event(false),
00079           m_notify_posedge_event(false), m_notify_negedge_event(false),
00080           m_output_port(0), m_driver_proc(0)
00081         { }
00082 
00083 public:
00084 
00085 /* interface methods */
00086 
00087     virtual const char* kind() const
00088         { return "rc_signal"; }
00089 
00090     virtual void register_port(sc_port_base& port_, const char* if_name_);
00091 
00092     virtual const sc_event& default_event() const
00093     { m_notify_value_changed_event = true; return m_value_changed_event; }
00094 
00095     virtual const sc_event& value_changed_event() const
00096     { m_notify_value_changed_event = true; return m_value_changed_event; }
00097 
00098     virtual const T& read() const
00099         { return m_current_value; }
00100 
00101     virtual const T& get_data_ref() const
00102         { return m_current_value; }
00103 
00104     virtual bool event() const
00105         { return (m_delta == sc_delta_count()); }
00106 
00107     virtual void write(const T& value);
00108 
00109     virtual void print(std::ostream& os=std::cout) const
00110         { os << m_current_value; }
00111 
00112     virtual void dump(std::ostream& os=std::cout) const;
00113 
00114 protected:
00115 
00116     virtual void update();
00117 
00118     RC_ON_INIT_RESETTABLE()
00119     {
00120         // store signal's initial value
00121         m_reset_value = m_new_value;
00122     }
00123 
00124     RC_ON_RESET()
00125     {
00126         // reset the signal
00127         m_delta = ~0;
00128         m_new_value = m_reset_value;
00129         m_current_value = m_reset_value;
00130         if (m_notify_value_changed_event) {
00131             m_value_changed_event.cancel();
00132         }
00133     }
00134 
00135 protected:
00136     T             m_current_value;
00137     sc_dt::uint64 m_delta;
00138     T             m_new_value;
00139     T             m_reset_value;
00140 
00141     mutable bool  m_notify_value_changed_event : 1;
00142     mutable bool  m_notify_posedge_event       : 1;
00143     mutable bool  m_notify_negedge_event       : 1;
00144     sc_event      m_value_changed_event;
00145 
00146     sc_port_base* m_output_port;
00147     sc_object*    m_driver_proc;
00148 
00149 private:
00150     // disabled
00151     rc_signal_b(const rc_signal_b<T>& other);
00152     rc_signal_b<T>& operator=(const rc_signal_b<T>& value);
00153 };
00154 
00158 template<class T>
00159 class rc_signal
00160     : public rc_signal_b<T>
00161 {
00162 private:
00163     typedef rc_signal<T>   this_type;
00164     typedef rc_signal_b<T> base_type;
00165 
00166 public:
00167     explicit rc_signal(
00168         const sc_module_name& name_=sc_gen_unique_name("signal"))
00169         : base_type(name_)
00170         { }
00171 
00172     operator const T&() const
00173         { return this->read(); }
00174 
00175     this_type& operator=(const T& value)
00176         { this->write(value); return *this; }
00177 
00178     this_type& operator=(const this_type& signal_)
00179         { this->write(signal_.read()); return *this; }
00180 };
00181 
00185 template<>
00186 class rc_signal<bool>
00187     : public rc_signal_b<bool>,
00188       virtual public rc_reset_channel_if
00189 {
00190 private:
00191     typedef rc_signal<bool>   this_type;
00192     typedef rc_signal_b<bool> base_type;
00193 
00194     typedef std::set<rc_process_control*> pctrl_set;
00195 
00196 public:
00197     explicit rc_signal(
00198         const sc_module_name& name_=sc_gen_unique_name("signal"))
00199         : base_type(name_), p_reset_signal(NULL)
00200         { }
00201 
00202 /* interface methods */
00203 
00204     virtual const sc_event& posedge_event() const
00205         { m_notify_posedge_event = true; return m_posedge_event; }
00206 
00207     virtual const sc_event& negedge_event() const
00208         { m_notify_negedge_event = true; return m_negedge_event; }
00209 
00210     virtual bool posedge() const
00211         { return (this->event() && m_current_value); }
00212 
00213     virtual bool negedge() const
00214         { return (this->event() && !m_current_value); }
00215 
00216 #if !defined(RC_USE_NON_OSCI_KERNEL)
00217     // workaround to allow reset of CTHREADs with the OSCI Kernel
00218     virtual sc_reset* is_reset() const
00219     {
00220         return _rc_get_reset_signal().is_reset();
00221     }
00222 #endif // !defined(RC_USE_NON_OSCI_KERNEL)
00223 
00224 /* other methods */
00225 
00226     operator const bool&() const
00227         { return this->read(); }
00228 
00229     this_type& operator=(const bool& value)
00230         { this->write(value); return *this; }
00231 
00232     this_type& operator=(const this_type& signal_)
00233         { this->write(signal_.read()); return *this; }
00234 
00235 protected:
00236 
00237     virtual void register_process_control(
00238         rc_process_control& pctrl, bool active_level) const;
00239 
00240     virtual void unregister_process_control(
00241         rc_process_control& pctrl) const;
00242 
00243     virtual bool get_current_level() const;
00244 
00245     virtual const sc_signal<bool>* get_underlying_reset_signal() const;
00246 
00247     virtual void update();
00248 
00249     RC_ON_RESET()
00250     {
00251         base_type::rc_on_reset();
00252 
00253         // reset the signal
00254         if (m_notify_negedge_event) {
00255             m_negedge_event.cancel();
00256         }
00257         if (m_notify_posedge_event) {
00258             m_posedge_event.cancel();
00259         }
00260     }
00261 
00262 private:
00263     sc_signal<bool>& _rc_get_reset_signal() const;
00264 
00265     void _rc_reset_updater_proc();
00266 
00267 protected:
00268     sc_event m_posedge_event;
00269     sc_event m_negedge_event;
00270 
00271 private:
00272     mutable pctrl_set        p_pctrl_set[2];
00273     mutable sc_signal<bool>* p_reset_signal;
00274 };
00275 
00279 template<>
00280 class rc_signal<sc_dt::sc_logic>
00281     : public rc_signal_b<sc_dt::sc_logic>
00282 {
00283 private:
00284     typedef rc_signal<sc_dt::sc_logic>   this_type;
00285     typedef rc_signal_b<sc_dt::sc_logic> base_type;
00286 
00287 public:
00288     explicit rc_signal(
00289         const sc_module_name& name_=sc_gen_unique_name("signal"))
00290         : base_type(name_)
00291         { }
00292 
00293 /* interface methods */
00294 
00295     virtual const sc_event& posedge_event() const
00296         { m_notify_posedge_event = true; return m_posedge_event; }
00297 
00298     virtual const sc_event& negedge_event() const
00299         { m_notify_negedge_event = true; return m_negedge_event; }
00300 
00301     virtual bool posedge() const
00302     { return (this->event() && m_current_value == sc_dt::SC_LOGIC_1); }
00303 
00304     virtual bool negedge() const
00305     { return (this->event() && m_current_value == sc_dt::SC_LOGIC_0); }
00306 
00307 /* other methods */
00308 
00309     operator const sc_dt::sc_logic&() const
00310         { return this->read(); }
00311 
00312     this_type& operator=(const sc_dt::sc_logic& value)
00313         { this->write(value); return *this; }
00314 
00315     this_type& operator=(const this_type& signal_)
00316         { this->write(signal_.read()); return *this; }
00317 
00318 protected:
00319 
00320     virtual void update();
00321 
00322     RC_ON_RESET()
00323     {
00324         base_type::rc_on_reset();
00325 
00326         // reset the signal
00327         if (m_notify_negedge_event) {
00328             m_negedge_event.cancel();
00329         }
00330         if (m_notify_posedge_event) {
00331             m_posedge_event.cancel();
00332         }
00333     }
00334 
00335 protected:
00336     sc_event m_posedge_event;
00337     sc_event m_negedge_event;
00338 };
00339 
00340 /* template code */
00341 
00342 template<class T>
00343 void rc_signal_b<T>::register_port(
00344     sc_port_base& port_, const char* if_name_)
00345 {
00346     std::string if_name(if_name_);
00347     if (if_name == typeid(sc_signal_inout_if<T>).name()) {
00348         if (m_output_port != NULL) {
00349             internals::signals::report_binding_error(
00350                 *this, *m_output_port, port_);
00351         }
00352         m_output_port = &port_;
00353     }
00354 }
00355 
00356 template<class T>
00357 void rc_signal_b<T>::write(const T& value)
00358 {
00359     if (this->rc_is_active() || !sc_is_running()) {
00360         if (this->rc_is_constr_done()) {
00361             sc_object* driver_proc =
00362                 sc_get_current_process_handle().get_process_object();
00363             if (m_driver_proc == NULL) {
00364                 m_driver_proc = driver_proc;
00365             } else if (m_driver_proc != driver_proc && driver_proc != NULL) {
00366                 internals::signals::report_driver_conflict(
00367                     *this, *m_driver_proc, *driver_proc);
00368             }
00369         }
00370 
00371         m_new_value = value;
00372         if (!(m_new_value == m_current_value)) {
00373             this->request_update();
00374         }
00375     }
00376 }
00377 
00378 template<class T>
00379 void rc_signal_b<T>::dump(std::ostream& os) const
00380 {
00381     os << "     name = " << this->name() << std::endl;
00382     os << "    value = " << m_current_value << std::endl;
00383     os << "new value = " << m_new_value << std::endl;
00384 }
00385 
00386 template<class T>
00387 void rc_signal_b<T>::update()
00388 {
00389     if (this->rc_is_active() && !(m_new_value == m_current_value)) {
00390         m_current_value = m_new_value;
00391         if (m_notify_value_changed_event) {
00392             m_value_changed_event.notify(SC_ZERO_TIME);
00393         }
00394         m_delta = sc_delta_count();
00395     }
00396 }
00397 
00398 } // namespace ReChannel
00399 
00400 #endif // RC_SIGNAL_H_
00401 
00402 //
00403 // $Id: rc_signal.h,v 1.11 2007/12/20 20:33:51 felke Exp $
00404 // $Source: /var/cvs/projekte/ReChannel-v2/src/ReChannel/components/rc_signal.h,v $
00405 //

Generated on Tue Jan 1 23:13:58 2008 for ReChannel by  doxygen 1.5.3