00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
00211 if (when==sc_core::SC_ZERO_TIME) {
00212 if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1)
00213 m_even_delta.insert(PAYLOAD(&t,p));
00214 else
00215 m_uneven_delta.insert(PAYLOAD(&t,p));
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);
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();
00227 }
00228
00229 private:
00230
00231 void fec(){
00232
00233 while(m_immediate_yield.next()) {PAYLOAD& tmp=m_immediate_yield.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);}
00234 m_immediate_yield.reset();
00235
00236
00237 if (sc_core::sc_delta_count() & (sc_dt::uint64) 0x1) {
00238 while (m_uneven_delta.next()) {PAYLOAD& tmp=m_uneven_delta.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);}
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);}
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;
00248
00249
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) {
00254 PAYLOAD& tmp=m_ppq.top();
00255 (m_owner->*m_cb)(*tmp.first, tmp.second);
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;
00274 };
00275
00276 }
00277
00278 #endif // __PEQ_WITH_CB_AND_PHASE_H__