rc_fifo.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_FIFO_H_
00038 #define RC_FIFO_H_
00039 
00040 #include "ReChannel/components/rc_prim_channel.h"
00041 #include "ReChannel/components/rc_report_ids.h"
00042 #include <deque>
00043 
00044 namespace ReChannel {
00045 
00049 template<class T>
00050 class rc_fifo
00051     : public sc_fifo_in_if<T>,
00052       public sc_fifo_out_if<T>,
00053       public rc_prim_channel
00054 {
00055 public:
00056 
00057     explicit rc_fifo(int size_=16)
00058         : rc_prim_channel(sc_gen_unique_name("fifo")),
00059           m_max_size(size_), m_num_read(0), m_num_written(0),
00060           m_reader_port(NULL), m_writer_port(NULL)
00061         { }
00062 
00063     explicit rc_fifo(const char* name_, int size_=16)
00064         : rc_prim_channel(name_),
00065           m_max_size(size_), m_num_read(0), m_num_written(0),
00066           m_reader_port(NULL), m_writer_port(NULL)
00067         { }
00068 
00069     virtual const char* kind() const
00070         { return "rc_fifo"; }
00071 
00072     virtual void register_port(sc_port_base& port_, const char* if_name_);
00073 
00074     inline virtual void read(T& value);
00075     inline virtual T read();
00076     inline virtual bool nb_read(T& value);
00077     inline virtual int num_available() const;
00078 
00079     inline virtual void write(const T& value);
00080     inline virtual bool nb_write(const T& value);
00081     inline virtual int num_free() const;
00082 
00083     virtual const sc_event& data_written_event() const
00084         { return m_data_written_event; }
00085     virtual const sc_event& data_read_event() const
00086         { return m_data_read_event; }
00087 
00088     operator T ()
00089         { return this->read(); }
00090 
00091     rc_fifo<T>& operator=(const T& value)
00092         { this->write(value); return *this; }
00093 
00094     virtual void print(std::ostream& os=std::cout) const;
00095     virtual void dump(std::ostream& os=std::cout) const;
00096 
00097 protected:
00098 
00099     virtual void update();
00100 
00101     RC_ON_INIT_RESETTABLE()
00102     {
00103         // store fifo's initial state
00104         if (!m_deque.empty()) {
00105             m_reset_values.insert(
00106                 m_reset_values.end(), m_deque.begin(), m_deque.end());
00107         }
00108     }
00109 
00110     RC_ON_RESET()
00111     {
00112         // clear the FIFO
00113         m_deque.clear();
00114         m_num_read = 0;
00115         m_num_written = 0;
00116         m_data_read_event.cancel();
00117         m_data_written_event.cancel();
00118 
00119         // restore fifo's initial state
00120         if (!m_reset_values.empty()) {
00121             m_deque.insert(
00122                 m_deque.end(), m_reset_values.begin(),
00123                 m_reset_values.end());
00124         }
00125     }
00126 
00127 protected:
00128 
00129     std::deque<T>       m_deque;
00130     const unsigned int  m_max_size;
00131     unsigned int        m_num_read;
00132     unsigned int        m_num_written;
00133 
00134     sc_event            m_data_read_event;
00135     sc_event            m_data_written_event;
00136 
00137     const sc_port_base* m_reader_port;
00138     const sc_port_base* m_writer_port;
00139 
00140     std::vector<T>      m_reset_values;
00141 
00142 private:
00143     // disabled
00144     rc_fifo(const rc_fifo<T>& other);
00145     rc_fifo<T>& operator=(const rc_fifo<T>& other);
00146 };
00147 
00148 /* inline code */
00149 
00150 template<class T>
00151 inline int rc_fifo<T>::num_available() const
00152 {
00153     if (!this->rc_is_active()) {
00154         return 0;
00155     }
00156     return (int)(m_deque.size() - m_num_written);
00157 }
00158 
00159 template<class T>
00160 inline int rc_fifo<T>::num_free() const
00161 {
00162     if (!this->rc_is_active()) {
00163         return 0;
00164     }
00165     return m_max_size - m_deque.size();
00166 }
00167 
00168 template<class T>
00169 inline void rc_fifo<T>::read(T& value)
00170 {
00171     while (this->num_available() == 0) {
00172         this->wait(m_data_written_event);
00173     }
00174     value = m_deque.front();
00175     m_deque.pop_front();
00176     m_num_read++;
00177     this->request_update();
00178 }
00179 
00180 template<class T>
00181 inline T rc_fifo<T>::read()
00182 {
00183     T tmp;
00184     this->read(tmp);
00185     return tmp;
00186 }
00187 
00188 template<class T>
00189 inline bool rc_fifo<T>::nb_read(T& value)
00190 {
00191     if (this->num_available() == 0) {
00192         return false;
00193     } else {
00194         value = m_deque.front();
00195         m_deque.pop_front();
00196         m_num_read++;
00197         this->request_update();
00198         return true;
00199     }
00200 }
00201 
00202 template<class T>
00203 inline void rc_fifo<T>::write(const T& value)
00204 {
00205     while(this->num_free() == 0) {
00206         this->wait(m_data_read_event);
00207     }
00208     m_num_written++;
00209     m_deque.push_back(value);
00210     this->request_update();
00211 }
00212 
00213 template<class T>
00214 inline bool rc_fifo<T>::nb_write(const T& value)
00215 {
00216     if (this->num_free() == 0) {
00217         return false;
00218     } else {
00219         m_num_written++;
00220         m_deque.push_back(value);
00221         this->request_update();
00222         return true;
00223     }
00224 }
00225 
00226 /* template code */
00227 
00228 template<class T>
00229 void rc_fifo<T>::register_port(
00230     sc_port_base& port_, const char* if_name_)
00231 {
00232     const std::string if_name(if_name_);
00233     if (if_name == typeid(sc_fifo_in_if<T>).name()) {
00234         if (m_reader_port != NULL) {
00235             RC_REPORT_ERROR(RC_ID_FIFO_BINDING_ERROR_,
00236                 "more than one FIFO reader"
00237                 " (in rc_fifo '" << this->name() << "')");
00238         }
00239         m_reader_port = &port_;
00240     } else { // if_name == typeid(sc_fifo_out_if<T>).name()
00241         if (m_writer_port != NULL) {
00242             RC_REPORT_ERROR(RC_ID_FIFO_BINDING_ERROR_,
00243                 "more than one FIFO writer"
00244                 " (in rc_fifo '" << this->name() << "')");
00245         }
00246         m_writer_port = &port_;
00247     }
00248 }
00249 
00250 template<class T>
00251 void rc_fifo<T>::print(std::ostream& os) const
00252 {
00253     for(typename std::deque<T>::const_reverse_iterator it =
00254         m_deque.rbegin();
00255         it != m_deque.rend();
00256         ++it)
00257     {
00258         os << (*it) << std::endl;
00259     }
00260 }
00261 
00262 template<class T>
00263 void rc_fifo<T>::dump(std::ostream& os) const
00264 {
00265     os << "name = " << this->name() << ::std::endl;
00266     unsigned int i = 0;
00267     for(typename std::deque<T>::const_iterator it = m_deque.begin();
00268         it != m_deque.end();
00269         ++it)
00270     {
00271         os << "value[" << i << "] = " << (*it) << ::std::endl;
00272         ++i;
00273     }
00274 }
00275 
00276 template<class T>
00277 void rc_fifo<T>::update()
00278 {
00279     if (this->rc_is_active()) {
00280         if (m_num_read > 0) {
00281             m_data_read_event.notify(SC_ZERO_TIME);
00282         }
00283         if (m_num_written > 0) {
00284             m_data_written_event.notify(SC_ZERO_TIME);
00285         }
00286     }
00287     m_num_read = 0;
00288     m_num_written = 0;
00289 }
00290 
00291 } // namespace ReChannel
00292 
00293 #endif //RC_FIFO_H_
00294 
00295 //
00296 // $Id: rc_fifo.h,v 1.10 2007/12/20 20:33:51 felke Exp $
00297 // $Source: /var/cvs/projekte/ReChannel-v2/src/ReChannel/components/rc_fifo.h,v $
00298 //

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