00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00219 if (when==sc_core::SC_ZERO_TIME) {
00220 if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1)
00221 m_even_delta.insert(PAYLOAD(&t,p));
00222 else
00223 m_uneven_delta.insert(PAYLOAD(&t,p));
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);
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();
00235 }
00236
00237
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
00250 while(m_immediate_yield.next()) {PAYLOAD& tmp=m_immediate_yield.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);}
00251 m_immediate_yield.reset();
00252
00253
00254 if (sc_core::sc_delta_count() & (sc_dt::uint64) 0x1) {
00255 while (m_uneven_delta.next()) {PAYLOAD& tmp=m_uneven_delta.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);}
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);}
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;
00265
00266
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) {
00271 PAYLOAD& tmp=m_ppq.top();
00272 (m_owner->*m_cb)(*tmp.first, tmp.second);
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;
00291 };
00292
00293 }
00294
00295 #endif // __PEQ_WITH_CB_AND_PHASE_H__