C:/ESLX/projects/TLMWG/tlm2/include/tlm/tlm_utils/peq_with_cb_and_phase.h

Go to the documentation of this file.
00001 /*****************************************************************************
00002 
00003   The following code is derived, directly or indirectly, from the SystemC
00004   source code Copyright (c) 1996-2008 by all Contributors.
00005   All Rights reserved.
00006 
00007   The contents of this file are subject to the restrictions and limitations
00008   set forth in the SystemC Open Source License Version 2.4 (the "License");
00009   You may not use this file except in compliance with such restrictions and
00010   limitations. You may obtain instructions on how to receive a copy of the
00011   License at http://www.systemc.org/. Software distributed by Contributors
00012   under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
00013   ANY KIND, either express or implied. See the License for the specific
00014   language governing rights and limitations under the License.
00015 
00016  *****************************************************************************/
00017 #ifndef __PEQ_WITH_CB_AND_PHASE_H__
00018 #define __PEQ_WITH_CB_AND_PHASE_H__
00019 
00020 #include <vector>
00021 #include <systemc>
00022 #include "tlm.h"
00023 
00024 namespace tlm_utils {
00025 
00026 template <typename PAYLOAD>
00027 class time_ordered_list
00028 {
00029 public:
00030   struct element
00031   {
00032     struct element  *next;
00033     PAYLOAD p;
00034     sc_core::sc_time t;
00035     sc_dt::uint64 d;
00036     element(PAYLOAD& p, sc_core::sc_time t, sc_dt::uint64 d): p(p),t(t),d(d) {}
00037     element(){}
00038   };
00039   
00040   element *nill;
00041   element *empties;
00042   element *list;
00043   unsigned int size;
00044     
00045   time_ordered_list() 
00046     : nill(new element()),
00047       empties(NULL),
00048       list(nill),
00049       size(0)
00050   {
00051   }
00052   
00053   ~time_ordered_list() {
00054     while(size) {
00055       delete_top();
00056     }
00057 
00058     while(empties){
00059       struct element *e=empties->next;
00060       delete empties;
00061       empties=e;
00062     }
00063     delete nill;
00064   }
00065   
00066   void insert(const PAYLOAD& p, sc_core::sc_time t) {
00067     if (!empties) {
00068       empties=new struct element();
00069       empties->next=NULL;
00070     }
00071     
00072     struct element *e=empties;
00073     empties=empties->next;
00074     e->p=p;
00075     e->t=t;
00076     e->d=sc_core::sc_delta_count();
00077     
00078     struct element * ancestor=nill;
00079     struct element * iterator=list;
00080     while (iterator!=nill && iterator->t<=t){
00081       ancestor=iterator;
00082       iterator=iterator->next;
00083     }
00084     if (ancestor==nill){
00085       e->next=list;
00086       list=e;
00087     }
00088     else {
00089       e->next=iterator;
00090       ancestor->next=e;
00091     }
00092     size++;
00093   }
00094   
00095   void delete_top(){
00096     if (list != nill) {
00097       struct element *e=list;
00098       list=list->next;
00099       e->next=empties;
00100       empties=e;
00101       size--;
00102     }
00103   }
00104   
00105   unsigned int get_size()
00106   {
00107     return size;
00108   }
00109   
00110   PAYLOAD &top()
00111   {
00112     return list->p;
00113   }
00114   sc_core::sc_time top_time()
00115   {
00116     return list->t;
00117   }
00118 
00119   sc_dt::uint64& top_delta()
00120   {
00121     return list->d;
00122   }
00123 
00124   sc_core::sc_time next_time()
00125   {
00126     return list->next->t;
00127   }
00128 };
00129 
00130 //---------------------------------------------------------------------------
00135 //---------------------------------------------------------------------------
00136 template<typename OWNER,typename TYPES=tlm::tlm_base_protocol_types>
00137 class peq_with_cb_and_phase: 
00138   public sc_core::sc_object
00139 {
00140 
00141   typedef typename TYPES::tlm_payload_type tlm_payload_type;
00142   typedef typename TYPES::tlm_phase_type   tlm_phase_type;
00143   typedef std::pair<tlm_payload_type*, tlm_phase_type> PAYLOAD;
00144   typedef void (OWNER::*cb)(tlm_payload_type&, const tlm_phase_type&);
00145   
00146   class delta_list{
00147   public:
00148     delta_list(){
00149       reset();
00150       entries.resize(100);
00151     }
00152     
00153     inline void insert(const PAYLOAD& p){
00154       if (size==entries.size()){
00155         entries.resize(entries.size()*2);
00156       }
00157       entries[size++]=p;
00158     }
00159     
00160     inline PAYLOAD& get(){
00161       return entries[out++];
00162     }
00163     
00164     inline bool next(){
00165       return out<size;
00166     }
00167     
00168     inline void reset(){
00169       size=0;
00170       out=0;
00171     }
00172   public:
00173     unsigned int size;
00174   private:
00175     std::vector<PAYLOAD> entries;
00176     unsigned int out;
00177   };
00178 
00179 public:
00180   
00181   peq_with_cb_and_phase(OWNER* _owner, cb _cb)
00182     :sc_core::sc_object( sc_core::sc_gen_unique_name( "peq_with_cb_and_phase" ) )
00183     ,m_owner(_owner)
00184     ,m_cb(_cb)
00185   {
00186     sc_core::sc_spawn_options opts;
00187     opts.spawn_method();
00188     opts.set_sensitivity(&m_e);
00189     opts.dont_initialize();
00190     sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this), 
00191                       sc_core::sc_gen_unique_name("fec"), &opts);
00192   }
00193 
00194   peq_with_cb_and_phase(const char* _name, OWNER* _owner,cb _cb)
00195     : sc_core::sc_object( _name )
00196     ,m_owner(_owner)
00197     ,m_cb(_cb)
00198   {
00199     sc_core::sc_spawn_options opts;
00200     opts.spawn_method();
00201     opts.set_sensitivity(&m_e);
00202     opts.dont_initialize();
00203     sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this), 
00204                       sc_core::sc_gen_unique_name("fec"), &opts);
00205   }
00206   
00207   ~peq_with_cb_and_phase(){}
00208   
00209   void notify (tlm_payload_type& t, tlm_phase_type& p, const sc_core::sc_time& when){
00210     //t.aquire();
00211     if (when==sc_core::SC_ZERO_TIME) {
00212       if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1) //uneven delta cycle so delta delay is for even cylce
00213         m_even_delta.insert(PAYLOAD(&t,p));
00214       else
00215         m_uneven_delta.insert(PAYLOAD(&t,p)); //even delta cycle so delta delay is for uneven delta
00216       m_e.notify(sc_core::SC_ZERO_TIME);
00217     }
00218     else {
00219       m_ppq.insert(PAYLOAD(&t,p),  when + sc_core::sc_time_stamp() );
00220       m_e.notify(when); // note, this will only over-right the "newest" event.
00221     }
00222   }
00223 
00224   void notify (tlm_payload_type& t, tlm_phase_type& p){
00225     m_immediate_yield.insert(PAYLOAD(&t,p));
00226     m_e.notify(); // immediate notification
00227   }
00228   
00229 private:
00230   
00231   void fec(){
00232     //immediate yield notifications
00233     while(m_immediate_yield.next()) {PAYLOAD& tmp=m_immediate_yield.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();}
00234     m_immediate_yield.reset();
00235     
00236     //delta notifications
00237     if (sc_core::sc_delta_count() & (sc_dt::uint64) 0x1) {//uneven delta so put out all payloads for uneven delta
00238       while (m_uneven_delta.next()) {PAYLOAD& tmp=m_uneven_delta.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();}
00239       m_uneven_delta.reset();
00240       if (m_even_delta.size) m_e.notify(sc_core::SC_ZERO_TIME);
00241     }
00242     else {
00243       while (m_even_delta.next()) {PAYLOAD& tmp=m_even_delta.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();}
00244       m_even_delta.reset();  
00245       if (m_uneven_delta.size) m_e.notify(sc_core::SC_ZERO_TIME);
00246     }
00247     if (!m_ppq.get_size()) return; //there were only delta notification
00248     
00249     //timed notifications
00250     const sc_core::sc_time now=sc_core::sc_time_stamp();
00251     sc_core::sc_time top=m_ppq.top_time();
00252 
00253     while(m_ppq.get_size() && top==now) { // push all active ones into target
00254       PAYLOAD& tmp=m_ppq.top();
00255       (m_owner->*m_cb)(*tmp.first, tmp.second); //tmp.first->release();}
00256       m_ppq.delete_top();
00257       top=m_ppq.top_time();
00258     }
00259     if ( m_ppq.get_size()) {
00260       m_e.notify( top - now) ;
00261     }
00262     
00263   }
00264   
00265   OWNER* m_owner;
00266   cb     m_cb;
00267   
00268   time_ordered_list<PAYLOAD> m_ppq;
00269   delta_list m_uneven_delta;
00270   delta_list m_even_delta;
00271   delta_list m_immediate_yield;
00272   
00273   sc_core::sc_event m_e;   // default event
00274 };
00275 
00276 }
00277 
00278 #endif // __PEQ_WITH_CB_AND_PHASE_H__

Generated on Thu Jun 5 17:43:04 2008 for TLM 2 by  doxygen 1.5.3