peq_with_cb_and_phase.h revision 13586
12SN/A/***************************************************************************** 21762SN/A 32SN/A Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 42SN/A more contributor license agreements. See the NOTICE file distributed 52SN/A with this work for additional information regarding copyright ownership. 62SN/A Accellera licenses this file to you under the Apache License, Version 2.0 72SN/A (the "License"); you may not use this file except in compliance with the 82SN/A License. You may obtain a copy of the License at 92SN/A 102SN/A http://www.apache.org/licenses/LICENSE-2.0 112SN/A 122SN/A Unless required by applicable law or agreed to in writing, software 132SN/A distributed under the License is distributed on an "AS IS" BASIS, 142SN/A WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 152SN/A implied. See the License for the specific language governing 162SN/A permissions and limitations under the License. 172SN/A 182SN/A *****************************************************************************/ 192SN/A 202SN/A#ifndef __SYSTEMC_EXT_TLM_UTILS_PEQ_WITH_CB_AND_PHASE_H__ 212SN/A#define __SYSTEMC_EXT_TLM_UTILS_PEQ_WITH_CB_AND_PHASE_H__ 222SN/A 232SN/A#include <vector> 242SN/A 252SN/A#include "../core/sc_main.hh" 262SN/A#include "../core/sc_object.hh" 272665Ssaidi@eecs.umich.edu#include "../core/sc_spawn.hh" 282665Ssaidi@eecs.umich.edu#include "../core/sc_time.hh" 292665Ssaidi@eecs.umich.edu#include "../dt/int/sc_nbdefs.hh" 302665Ssaidi@eecs.umich.edu 312665Ssaidi@eecs.umich.edunamespace tlm_utils 322SN/A{ 332SN/A 342SN/Atemplate <typename PAYLOAD> 352SN/Aclass time_ordered_list 367349SAli.Saidi@ARM.com{ 3756SN/A public: 381717SN/A struct element 392518SN/A { 4056SN/A struct element *next; 414776Sgblack@eecs.umich.edu PAYLOAD p; 426658Snate@binkert.org sc_core::sc_time t; 434762Snate@binkert.org sc_dt::uint64 d; 443065Sgblack@eecs.umich.edu element(PAYLOAD &p, sc_core::sc_time t, sc_dt::uint64 d) : 452SN/A p(p), t(t), d(d) 462973Sgblack@eecs.umich.edu {} 472SN/A element() {} 483506Ssaidi@eecs.umich.edu }; 494054Sbinkertn@umich.edu 504054Sbinkertn@umich.edu element *nill; 515866Sksewell@umich.edu element *empties; 525866Sksewell@umich.edu element *list; 535866Sksewell@umich.edu unsigned int size; 545866Sksewell@umich.edu 555866Sksewell@umich.edu time_ordered_list() : nill(new element()), empties(NULL), 565866Sksewell@umich.edu list(nill), size(0) 575784Sgblack@eecs.umich.edu {} 584054Sbinkertn@umich.edu 594776Sgblack@eecs.umich.edu ~time_ordered_list() 604054Sbinkertn@umich.edu { 614776Sgblack@eecs.umich.edu reset(); 625866Sksewell@umich.edu while (empties) { 634054Sbinkertn@umich.edu struct element *e = empties->next; 644776Sgblack@eecs.umich.edu delete empties; 654054Sbinkertn@umich.edu empties = e; 664776Sgblack@eecs.umich.edu } 674776Sgblack@eecs.umich.edu delete nill; 684054Sbinkertn@umich.edu } 694776Sgblack@eecs.umich.edu 705715Shsul@eecs.umich.edu void 714776Sgblack@eecs.umich.edu reset() 724776Sgblack@eecs.umich.edu { 734776Sgblack@eecs.umich.edu while (size) { 747349SAli.Saidi@ARM.com delete_top(); 757349SAli.Saidi@ARM.com } 767349SAli.Saidi@ARM.com } 777349SAli.Saidi@ARM.com 784776Sgblack@eecs.umich.edu void 794776Sgblack@eecs.umich.edu insert(const PAYLOAD &p, sc_core::sc_time t) 805947Sgblack@eecs.umich.edu { 815947Sgblack@eecs.umich.edu if (!empties) { 825947Sgblack@eecs.umich.edu empties = new struct element(); 837349SAli.Saidi@ARM.com empties->next=NULL; 847349SAli.Saidi@ARM.com } 857349SAli.Saidi@ARM.com 865784Sgblack@eecs.umich.edu struct element *e = empties; 874776Sgblack@eecs.umich.edu empties = empties->next; 884776Sgblack@eecs.umich.edu e->p = p; 897349SAli.Saidi@ARM.com e->t = t; 904776Sgblack@eecs.umich.edu e->d = sc_core::sc_delta_count(); 914776Sgblack@eecs.umich.edu 925784Sgblack@eecs.umich.edu struct element *ancestor = nill; 935784Sgblack@eecs.umich.edu struct element *iterator = list; 945784Sgblack@eecs.umich.edu while (iterator != nill && iterator->t <= t) { 955784Sgblack@eecs.umich.edu ancestor = iterator; 965784Sgblack@eecs.umich.edu iterator = iterator->next; 975784Sgblack@eecs.umich.edu } 985784Sgblack@eecs.umich.edu if (ancestor == nill) { 995784Sgblack@eecs.umich.edu e->next = list; 1004776Sgblack@eecs.umich.edu list = e; 1014776Sgblack@eecs.umich.edu } else { 1024776Sgblack@eecs.umich.edu e->next = iterator; 1034776Sgblack@eecs.umich.edu ancestor->next = e; 1044776Sgblack@eecs.umich.edu } 1057349SAli.Saidi@ARM.com size++; 1064776Sgblack@eecs.umich.edu } 1075784Sgblack@eecs.umich.edu 1085784Sgblack@eecs.umich.edu void 1095784Sgblack@eecs.umich.edu delete_top() 1105784Sgblack@eecs.umich.edu { 1115784Sgblack@eecs.umich.edu if (list != nill) { 1125784Sgblack@eecs.umich.edu struct element *e = list; 1135784Sgblack@eecs.umich.edu list = list->next; 1147600Sminkyu.jeong@arm.com e->next = empties; 1157600Sminkyu.jeong@arm.com empties = e; 1167600Sminkyu.jeong@arm.com size--; 1177600Sminkyu.jeong@arm.com } 1185784Sgblack@eecs.umich.edu } 1195784Sgblack@eecs.umich.edu 1205784Sgblack@eecs.umich.edu unsigned int get_size() { return size; } 1215784Sgblack@eecs.umich.edu PAYLOAD &top() { return list->p; } 1225784Sgblack@eecs.umich.edu sc_core::sc_time top_time() { return list->t; } 1235784Sgblack@eecs.umich.edu sc_dt::uint64 &top_delta() { return list->d; } 1245784Sgblack@eecs.umich.edu sc_core::sc_time next_time() { return list->next->t; } 1255784Sgblack@eecs.umich.edu}; 1265784Sgblack@eecs.umich.edu 1275784Sgblack@eecs.umich.edu//--------------------------------------------------------------------------- 1285784Sgblack@eecs.umich.edu/** 1295784Sgblack@eecs.umich.edu * An event queue that can contain any number of pending 1304776Sgblack@eecs.umich.edu * notifications. Each notification have an associate payload. 1314776Sgblack@eecs.umich.edu */ 1324776Sgblack@eecs.umich.edu//--------------------------------------------------------------------------- 1334776Sgblack@eecs.umich.edutemplate<typename OWNER, typename TYPES=tlm::tlm_base_protocol_types> 1344776Sgblack@eecs.umich.educlass peq_with_cb_and_phase : public sc_core::sc_object 1354776Sgblack@eecs.umich.edu{ 1363506Ssaidi@eecs.umich.edu typedef typename TYPES::tlm_payload_type tlm_payload_type; 1373506Ssaidi@eecs.umich.edu typedef typename TYPES::tlm_phase_type tlm_phase_type; 1385784Sgblack@eecs.umich.edu typedef std::pair<tlm_payload_type *, tlm_phase_type> PAYLOAD; 1395784Sgblack@eecs.umich.edu typedef void (OWNER::*cb)(tlm_payload_type &, const tlm_phase_type &); 1405784Sgblack@eecs.umich.edu 1415784Sgblack@eecs.umich.edu class delta_list 1425784Sgblack@eecs.umich.edu { 1435784Sgblack@eecs.umich.edu public: 1445784Sgblack@eecs.umich.edu delta_list() 1455784Sgblack@eecs.umich.edu { 1465784Sgblack@eecs.umich.edu reset(); 1475784Sgblack@eecs.umich.edu entries.resize(100); 1485784Sgblack@eecs.umich.edu } 1495784Sgblack@eecs.umich.edu 1505791Srstrong@cs.ucsd.edu inline void 1515784Sgblack@eecs.umich.edu insert(const PAYLOAD &p) 1525784Sgblack@eecs.umich.edu { 1535791Srstrong@cs.ucsd.edu if (size==entries.size()) { 1545784Sgblack@eecs.umich.edu entries.resize(entries.size() * 2); 1555784Sgblack@eecs.umich.edu } 1565784Sgblack@eecs.umich.edu entries[size++] = p; 1575784Sgblack@eecs.umich.edu } 1585784Sgblack@eecs.umich.edu 1595784Sgblack@eecs.umich.edu inline PAYLOAD &get() { return entries[out++]; } 1605784Sgblack@eecs.umich.edu inline bool next() { return out < size; } 1614776Sgblack@eecs.umich.edu inline void 1624776Sgblack@eecs.umich.edu reset() 1632SN/A { 1642SN/A size=0; 1654776Sgblack@eecs.umich.edu out=0; 1662SN/A } 1674776Sgblack@eecs.umich.edu 1684776Sgblack@eecs.umich.edu public: 1693748Sgblack@eecs.umich.edu unsigned int size; 1705034Smilesck@eecs.umich.edu 1714776Sgblack@eecs.umich.edu private: 172 std::vector<PAYLOAD> entries; 173 unsigned int out; 174 }; 175 176 public: 177 peq_with_cb_and_phase(OWNER *_owner, cb _cb) : 178 sc_core::sc_object(sc_core::sc_gen_unique_name( 179 "peq_with_cb_and_phase")), 180 m_owner(_owner), m_cb(_cb) 181 { 182 sc_core::sc_spawn_options opts; 183 opts.spawn_method(); 184 opts.set_sensitivity(&m_e); 185 opts.dont_initialize(); 186 sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this), 187 sc_core::sc_gen_unique_name("fec"), &opts); 188 } 189 190 peq_with_cb_and_phase(const char *_name, OWNER *_owner, cb _cb) : 191 sc_core::sc_object(_name), m_owner(_owner), m_cb(_cb) 192 { 193 sc_core::sc_spawn_options opts; 194 opts.spawn_method(); 195 opts.set_sensitivity(&m_e); 196 opts.dont_initialize(); 197 sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this), 198 sc_core::sc_gen_unique_name("fec"), &opts); 199 } 200 201 ~peq_with_cb_and_phase() {} 202 203 void 204 notify(tlm_payload_type &t, const tlm_phase_type &p, 205 const sc_core::sc_time &when) 206 { 207 if (when == sc_core::SC_ZERO_TIME) { 208 if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1) { 209 // Uneven delta cycle so delta delay is for even cycle. 210 m_even_delta.insert(PAYLOAD(&t,p)); 211 } else { 212 // Even delta cycle so delta delay is for uneven delta. 213 m_uneven_delta.insert(PAYLOAD(&t, p)); 214 } 215 m_e.notify(sc_core::SC_ZERO_TIME); 216 } else { 217 m_ppq.insert(PAYLOAD(&t, p), when + sc_core::sc_time_stamp()); 218 // Note, this will only overwrite the "newest" event. 219 m_e.notify(when); 220 } 221 } 222 223 void 224 notify(tlm_payload_type &t, const tlm_phase_type &p) 225 { 226 m_immediate_yield.insert(PAYLOAD(&t, p)); 227 m_e.notify(); // Immediate notification. 228 } 229 230 // Cancel all events from the event queue. 231 void 232 cancel_all() 233 { 234 m_ppq.reset(); 235 m_uneven_delta.reset(); 236 m_even_delta.reset(); 237 m_immediate_yield.reset(); 238 m_e.cancel(); 239 } 240 241 private: 242 void 243 fec() 244 { 245 // Immediate yield notifications. 246 while (m_immediate_yield.next()) { 247 PAYLOAD &tmp = m_immediate_yield.get(); 248 (m_owner->*m_cb)(*tmp.first, tmp.second); 249 } 250 m_immediate_yield.reset(); 251 252 // Delta notifications. 253 if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1) { 254 // Uneven delta so put out all payloads for uneven delta. 255 while (m_uneven_delta.next()) { 256 PAYLOAD &tmp = m_uneven_delta.get(); 257 (m_owner->*m_cb)(*tmp.first, tmp.second); 258 } 259 m_uneven_delta.reset(); 260 if (m_even_delta.size) 261 m_e.notify(sc_core::SC_ZERO_TIME); 262 } else { 263 while (m_even_delta.next()) { 264 PAYLOAD &tmp = m_even_delta.get(); 265 (m_owner->*m_cb)(*tmp.first, tmp.second); 266 } 267 m_even_delta.reset(); 268 if (m_uneven_delta.size) 269 m_e.notify(sc_core::SC_ZERO_TIME); 270 } 271 if (!m_ppq.get_size()) 272 return; // There were only delta notification. 273 274 // Timed notifications. 275 const sc_core::sc_time now = sc_core::sc_time_stamp(); 276 sc_core::sc_time top = m_ppq.top_time(); 277 278 while (m_ppq.get_size() && top == now) { 279 // Push all active ones into target. 280 PAYLOAD &tmp = m_ppq.top(); 281 (m_owner->*m_cb)(*tmp.first, tmp.second); 282 m_ppq.delete_top(); 283 top = m_ppq.top_time(); 284 } 285 if (m_ppq.get_size()) { 286 m_e.notify(top - now); 287 } 288 } 289 290 OWNER *m_owner; 291 cb m_cb; 292 293 time_ordered_list<PAYLOAD> m_ppq; 294 delta_list m_uneven_delta; 295 delta_list m_even_delta; 296 delta_list m_immediate_yield; 297 298 sc_core::sc_event m_e; // Default event. 299}; 300 301} // namespace tlm_utils 302 303#endif /* __SYSTEMC_EXT_TLM_UTILS_PEQ_WITH_CB_AND_PHASE_H__ */ 304