TLM-2.0: include/tlm/tlm_utils/peq_with_cb_and_phase.h Source File

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# 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
    00018 // 12-Jan-2009  John Aynsley  Bug fix. Phase argument to notify should be const
    00019 // 20-Mar-2009  John Aynsley  Add cancel_all() method
    00020
    00021
    00022 #ifndef __PEQ_WITH_CB_AND_PHASE_H__
    00023 #define __PEQ_WITH_CB_AND_PHASE_H__
    00024
    00025 #include <vector>
    00026 #include <systemc>
    00027 #include "tlm.h"
    00028
    00029 namespace tlm_utils {
    00030
    00031 template <typename PAYLOAD>
    00032 class time_ordered_list
    00033 {
    00034 public:
    00035   struct element
    00036   {
    00037     struct element  *next;
    00038     PAYLOAD p;
    00039     sc_core::sc_time t;
    00040     sc_dt::uint64 d;
    00041     element(PAYLOAD& p, sc_core::sc_time t, sc_dt::uint64 d): p(p),t(t),d(d) {}
    00042     element(){}
    00043   };
    00044
    00045   element *nill;
    00046   element *empties;
    00047   element *list;
    00048   unsigned int size;
    00049
    00050   time_ordered_list()
    00051     : nill(new element()),
    00052       empties(NULL),
    00053       list(nill),
    00054       size(0)
    00055   {
    00056   }
    00057
    00058   ~time_ordered_list() {
    00059     reset();
    00060     while(empties){
    00061       struct element *e=empties->next;
    00062       delete empties;
    00063       empties=e;
    00064     }
    00065     delete nill;
    00066   }
    00067
    00068   void reset() {
    00069     while(size) {
    00070       delete_top();
    00071     }
    00072   }
    00073
    00074   void insert(const PAYLOAD& p, sc_core::sc_time t) {
    00075     if (!empties) {
    00076       empties=new struct element();
    00077       empties->next=NULL;
    00078     }
    00079
    00080     struct element *e=empties;
    00081     empties=empties->next;
    00082     e->p=p;
    00083     e->t=t;
    00084     e->d=sc_core::sc_delta_count();
    00085
    00086     struct element * ancestor=nill;
    00087     struct element * iterator=list;
    00088     while (iterator!=nill && iterator->t<=t){
    00089       ancestor=iterator;
    00090       iterator=iterator->next;
    00091     }
    00092     if (ancestor==nill){
    00093       e->next=list;
    00094       list=e;
    00095     }
    00096     else {
    00097       e->next=iterator;
    00098       ancestor->next=e;
    00099     }
    00100     size++;
    00101   }
    00102
    00103   void delete_top(){
    00104     if (list != nill) {
    00105       struct element *e=list;
    00106       list=list->next;
    00107       e->next=empties;
    00108       empties=e;
    00109       size--;
    00110     }
    00111   }
    00112
    00113   unsigned int get_size()
    00114   {
    00115     return size;
    00116   }
    00117
    00118   PAYLOAD &top()
    00119   {
    00120     return list->p;
    00121   }
    00122   sc_core::sc_time top_time()
    00123   {
    00124     return list->t;
    00125   }
    00126
    00127   sc_dt::uint64& top_delta()
    00128   {
    00129     return list->d;
    00130   }
    00131
    00132   sc_core::sc_time next_time()
    00133   {
    00134     return list->next->t;
    00135   }
    00136 };
    00137
    00138 //---------------------------------------------------------------------------
    00143 //---------------------------------------------------------------------------
    00144 template<typename OWNER,typename TYPES=tlm::tlm_base_protocol_types>
    00145 class peq_with_cb_and_phase:
    00146   public sc_core::sc_object
    00147 {
    00148
    00149   typedef typename TYPES::tlm_payload_type tlm_payload_type;
    00150   typedef typename TYPES::tlm_phase_type   tlm_phase_type;
    00151   typedef std::pair<tlm_payload_type*, tlm_phase_type> PAYLOAD;
    00152   typedef void (OWNER::*cb)(tlm_payload_type&, const tlm_phase_type&);
    00153
    00154   class delta_list{
    00155   public:
    00156     delta_list(){
    00157       reset();
    00158       entries.resize(100);
    00159     }
    00160
    00161     inline void insert(const PAYLOAD& p){
    00162       if (size==entries.size()){
    00163         entries.resize(entries.size()*2);
    00164       }
    00165       entries[size++]=p;
    00166     }
    00167
    00168     inline PAYLOAD& get(){
    00169       return entries[out++];
    00170     }
    00171
    00172     inline bool next(){
    00173       return out<size;
    00174     }
    00175
    00176     inline void reset(){
    00177       size=0;
    00178       out=0;
    00179     }
    00180   public:
    00181     unsigned int size;
    00182   private:
    00183     std::vector<PAYLOAD> entries;
    00184     unsigned int out;
    00185   };
    00186
    00187 public:
    00188
    00189   peq_with_cb_and_phase(OWNER* _owner, cb _cb)
    00190     :sc_core::sc_object( sc_core::sc_gen_unique_name( "peq_with_cb_and_phase" ) )
    00191     ,m_owner(_owner)
    00192     ,m_cb(_cb)
    00193   {
    00194     sc_core::sc_spawn_options opts;
    00195     opts.spawn_method();
    00196     opts.set_sensitivity(&m_e);
    00197     opts.dont_initialize();
    00198     sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this),
    00199                       sc_core::sc_gen_unique_name("fec"), &opts);
    00200   }
    00201
    00202   peq_with_cb_and_phase(const char* _name, OWNER* _owner,cb _cb)
    00203     : sc_core::sc_object( _name )
    00204     ,m_owner(_owner)
    00205     ,m_cb(_cb)
    00206   {
    00207     sc_core::sc_spawn_options opts;
    00208     opts.spawn_method();
    00209     opts.set_sensitivity(&m_e);
    00210     opts.dont_initialize();
    00211     sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this),
    00212                       sc_core::sc_gen_unique_name("fec"), &opts);
    00213   }
    00214
    00215   ~peq_with_cb_and_phase(){}
    00216
    00217   void notify (tlm_payload_type& t, const tlm_phase_type& p, const sc_core::sc_time& when){
    00218     //t.aquire();
    00219     if (when==sc_core::SC_ZERO_TIME) {
    00220       if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1) //uneven delta cycle so delta delay is for even cylce
    00221         m_even_delta.insert(PAYLOAD(&t,p));
    00222       else
    00223         m_uneven_delta.insert(PAYLOAD(&t,p)); //even delta cycle so delta delay is for uneven delta
    00224       m_e.notify(sc_core::SC_ZERO_TIME);
    00225     }
    00226     else {
    00227       m_ppq.insert(PAYLOAD(&t,p),  when + sc_core::sc_time_stamp() );
    00228       m_e.notify(when); // note, this will only over-right the "newest" event.
    00229     }
    00230   }
    00231
    00232   void notify (tlm_payload_type& t, const tlm_phase_type& p){
    00233     m_immediate_yield.insert(PAYLOAD(&t,p));
    00234     m_e.notify(); // immediate notification
    00235   }
    00236
    00237   // Cancel all events from the event queue
    00238   void cancel_all() {
    00239     m_ppq.reset();
    00240     m_uneven_delta.reset();
    00241     m_even_delta.reset();
    00242     m_immediate_yield.reset();
    00243     m_e.cancel();
    00244   }
    00245
    00246 private:
    00247
    00248   void fec(){
    00249     //immediate yield notifications
    00250     while(m_immediate_yield.next()) {PAYLOAD& tmp=m_immediate_yield.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();}
    00251     m_immediate_yield.reset();
    00252
    00253     //delta notifications
    00254     if (sc_core::sc_delta_count() & (sc_dt::uint64) 0x1) {//uneven delta so put out all payloads for uneven delta
    00255       while (m_uneven_delta.next()) {PAYLOAD& tmp=m_uneven_delta.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();}
    00256       m_uneven_delta.reset();
    00257       if (m_even_delta.size) m_e.notify(sc_core::SC_ZERO_TIME);
    00258     }
    00259     else {
    00260       while (m_even_delta.next()) {PAYLOAD& tmp=m_even_delta.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();}
    00261       m_even_delta.reset();
    00262       if (m_uneven_delta.size) m_e.notify(sc_core::SC_ZERO_TIME);
    00263     }
    00264     if (!m_ppq.get_size()) return; //there were only delta notification
    00265
    00266     //timed notifications
    00267     const sc_core::sc_time now=sc_core::sc_time_stamp();
    00268     sc_core::sc_time top=m_ppq.top_time();
    00269
    00270     while(m_ppq.get_size() && top==now) { // push all active ones into target
    00271       PAYLOAD& tmp=m_ppq.top();
    00272       (m_owner->*m_cb)(*tmp.first, tmp.second); //tmp.first->release();}
    00273       m_ppq.delete_top();
    00274       top=m_ppq.top_time();
    00275     }
    00276     if ( m_ppq.get_size()) {
    00277       m_e.notify( top - now) ;
    00278     }
    00279
    00280   }
    00281
    00282   OWNER* m_owner;
    00283   cb     m_cb;
    00284
    00285   time_ordered_list<PAYLOAD> m_ppq;
    00286   delta_list m_uneven_delta;
    00287   delta_list m_even_delta;
    00288   delta_list m_immediate_yield;
    00289
    00290   sc_core::sc_event m_e;   // default event
    00291 };
    00292
    00293 }
    00294
    00295 #endif // __PEQ_WITH_CB_AND_PHASE_H__