peq_with_cb_and_phase.h revision 13513
113511Sgabeblack@google.com/***************************************************************************** 213511Sgabeblack@google.com 313511Sgabeblack@google.com Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 413511Sgabeblack@google.com more contributor license agreements. See the NOTICE file distributed 513511Sgabeblack@google.com with this work for additional information regarding copyright ownership. 613511Sgabeblack@google.com Accellera licenses this file to you under the Apache License, Version 2.0 713511Sgabeblack@google.com (the "License"); you may not use this file except in compliance with the 813511Sgabeblack@google.com License. You may obtain a copy of the License at 913511Sgabeblack@google.com 1013511Sgabeblack@google.com http://www.apache.org/licenses/LICENSE-2.0 1113511Sgabeblack@google.com 1213511Sgabeblack@google.com Unless required by applicable law or agreed to in writing, software 1313511Sgabeblack@google.com distributed under the License is distributed on an "AS IS" BASIS, 1413511Sgabeblack@google.com WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 1513511Sgabeblack@google.com implied. See the License for the specific language governing 1613511Sgabeblack@google.com permissions and limitations under the License. 1713511Sgabeblack@google.com 1813511Sgabeblack@google.com *****************************************************************************/ 1913511Sgabeblack@google.com 2013513Sgabeblack@google.com#ifndef __SYSTEMC_EXT_TLM_UTILS_PEQ_WITH_CB_AND_PHASE_H__ 2113513Sgabeblack@google.com#define __SYSTEMC_EXT_TLM_UTILS_PEQ_WITH_CB_AND_PHASE_H__ 2213511Sgabeblack@google.com 2313511Sgabeblack@google.com#include <systemc> 2413511Sgabeblack@google.com#include <tlm> 2513513Sgabeblack@google.com#include <vector> 2613511Sgabeblack@google.com 2713513Sgabeblack@google.comnamespace tlm_utils 2813513Sgabeblack@google.com{ 2913511Sgabeblack@google.com 3013511Sgabeblack@google.comtemplate <typename PAYLOAD> 3113511Sgabeblack@google.comclass time_ordered_list 3213511Sgabeblack@google.com{ 3313513Sgabeblack@google.com public: 3413513Sgabeblack@google.com struct element 3513513Sgabeblack@google.com { 3613513Sgabeblack@google.com struct element *next; 3713513Sgabeblack@google.com PAYLOAD p; 3813513Sgabeblack@google.com sc_core::sc_time t; 3913513Sgabeblack@google.com sc_dt::uint64 d; 4013513Sgabeblack@google.com element(PAYLOAD &p, sc_core::sc_time t, sc_dt::uint64 d) : 4113513Sgabeblack@google.com p(p), t(t), d(d) 4213513Sgabeblack@google.com {} 4313513Sgabeblack@google.com element() {} 4413513Sgabeblack@google.com }; 4513511Sgabeblack@google.com 4613513Sgabeblack@google.com element *nill; 4713513Sgabeblack@google.com element *empties; 4813513Sgabeblack@google.com element *list; 4913513Sgabeblack@google.com unsigned int size; 5013511Sgabeblack@google.com 5113513Sgabeblack@google.com time_ordered_list() : nill(new element()), empties(NULL), 5213513Sgabeblack@google.com list(nill), size(0) 5313513Sgabeblack@google.com {} 5413511Sgabeblack@google.com 5513513Sgabeblack@google.com ~time_ordered_list() 5613513Sgabeblack@google.com { 5713513Sgabeblack@google.com reset(); 5813513Sgabeblack@google.com while (empties) { 5913513Sgabeblack@google.com struct element *e = empties->next; 6013513Sgabeblack@google.com delete empties; 6113513Sgabeblack@google.com empties = e; 6213513Sgabeblack@google.com } 6313513Sgabeblack@google.com delete nill; 6413511Sgabeblack@google.com } 6513511Sgabeblack@google.com 6613513Sgabeblack@google.com void 6713513Sgabeblack@google.com reset() 6813513Sgabeblack@google.com { 6913513Sgabeblack@google.com while (size) { 7013513Sgabeblack@google.com delete_top(); 7113513Sgabeblack@google.com } 7213513Sgabeblack@google.com } 7313511Sgabeblack@google.com 7413513Sgabeblack@google.com void 7513513Sgabeblack@google.com insert(const PAYLOAD &p, sc_core::sc_time t) 7613513Sgabeblack@google.com { 7713513Sgabeblack@google.com if (!empties) { 7813513Sgabeblack@google.com empties = new struct element(); 7913513Sgabeblack@google.com empties->next=NULL; 8013513Sgabeblack@google.com } 8113513Sgabeblack@google.com 8213513Sgabeblack@google.com struct element *e = empties; 8313513Sgabeblack@google.com empties = empties->next; 8413513Sgabeblack@google.com e->p = p; 8513513Sgabeblack@google.com e->t = t; 8613513Sgabeblack@google.com e->d = sc_core::sc_delta_count(); 8713513Sgabeblack@google.com 8813513Sgabeblack@google.com struct element *ancestor = nill; 8913513Sgabeblack@google.com struct element *iterator = list; 9013513Sgabeblack@google.com while (iterator != nill && iterator->t <= t) { 9113513Sgabeblack@google.com ancestor = iterator; 9213513Sgabeblack@google.com iterator = iterator->next; 9313513Sgabeblack@google.com } 9413513Sgabeblack@google.com if (ancestor == nill) { 9513513Sgabeblack@google.com e->next = list; 9613513Sgabeblack@google.com list = e; 9713513Sgabeblack@google.com } else { 9813513Sgabeblack@google.com e->next = iterator; 9913513Sgabeblack@google.com ancestor->next = e; 10013513Sgabeblack@google.com } 10113513Sgabeblack@google.com size++; 10213511Sgabeblack@google.com } 10313513Sgabeblack@google.com 10413513Sgabeblack@google.com void 10513513Sgabeblack@google.com delete_top() 10613513Sgabeblack@google.com { 10713513Sgabeblack@google.com if (list != nill) { 10813513Sgabeblack@google.com struct element *e = list; 10913513Sgabeblack@google.com list = list->next; 11013513Sgabeblack@google.com e->next = empties; 11113513Sgabeblack@google.com empties = e; 11213513Sgabeblack@google.com size--; 11313513Sgabeblack@google.com } 11413511Sgabeblack@google.com } 11513511Sgabeblack@google.com 11613513Sgabeblack@google.com unsigned int get_size() { return size; } 11713513Sgabeblack@google.com PAYLOAD &top() { return list->p; } 11813513Sgabeblack@google.com sc_core::sc_time top_time() { return list->t; } 11913513Sgabeblack@google.com sc_dt::uint64 &top_delta() { return list->d; } 12013513Sgabeblack@google.com sc_core::sc_time next_time() { return list->next->t; } 12113511Sgabeblack@google.com}; 12213511Sgabeblack@google.com 12313511Sgabeblack@google.com//--------------------------------------------------------------------------- 12413511Sgabeblack@google.com/** 12513511Sgabeblack@google.com * An event queue that can contain any number of pending 12613511Sgabeblack@google.com * notifications. Each notification have an associate payload. 12713511Sgabeblack@google.com */ 12813511Sgabeblack@google.com//--------------------------------------------------------------------------- 12913513Sgabeblack@google.comtemplate<typename OWNER, typename TYPES=tlm::tlm_base_protocol_types> 13013513Sgabeblack@google.comclass peq_with_cb_and_phase : public sc_core::sc_object 13113511Sgabeblack@google.com{ 13213513Sgabeblack@google.com typedef typename TYPES::tlm_payload_type tlm_payload_type; 13313513Sgabeblack@google.com typedef typename TYPES::tlm_phase_type tlm_phase_type; 13413513Sgabeblack@google.com typedef std::pair<tlm_payload_type *, tlm_phase_type> PAYLOAD; 13513513Sgabeblack@google.com typedef void (OWNER::*cb)(tlm_payload_type &, const tlm_phase_type &); 13613511Sgabeblack@google.com 13713513Sgabeblack@google.com class delta_list 13813513Sgabeblack@google.com { 13913513Sgabeblack@google.com public: 14013513Sgabeblack@google.com delta_list() 14113513Sgabeblack@google.com { 14213513Sgabeblack@google.com reset(); 14313513Sgabeblack@google.com entries.resize(100); 14413513Sgabeblack@google.com } 14513511Sgabeblack@google.com 14613513Sgabeblack@google.com inline void 14713513Sgabeblack@google.com insert(const PAYLOAD &p) 14813513Sgabeblack@google.com { 14913513Sgabeblack@google.com if (size==entries.size()) { 15013513Sgabeblack@google.com entries.resize(entries.size() * 2); 15113513Sgabeblack@google.com } 15213513Sgabeblack@google.com entries[size++] = p; 15313513Sgabeblack@google.com } 15413513Sgabeblack@google.com 15513513Sgabeblack@google.com inline PAYLOAD &get() { return entries[out++]; } 15613513Sgabeblack@google.com inline bool next() { return out < size; } 15713513Sgabeblack@google.com inline void 15813513Sgabeblack@google.com reset() 15913513Sgabeblack@google.com { 16013513Sgabeblack@google.com size=0; 16113513Sgabeblack@google.com out=0; 16213513Sgabeblack@google.com } 16313513Sgabeblack@google.com 16413513Sgabeblack@google.com public: 16513513Sgabeblack@google.com unsigned int size; 16613513Sgabeblack@google.com 16713513Sgabeblack@google.com private: 16813513Sgabeblack@google.com std::vector<PAYLOAD> entries; 16913513Sgabeblack@google.com unsigned int out; 17013513Sgabeblack@google.com }; 17113513Sgabeblack@google.com 17213511Sgabeblack@google.com public: 17313513Sgabeblack@google.com peq_with_cb_and_phase(OWNER *_owner, cb _cb) : 17413513Sgabeblack@google.com sc_core::sc_object(sc_core::sc_gen_unique_name( 17513513Sgabeblack@google.com "peq_with_cb_and_phase")), 17613513Sgabeblack@google.com m_owner(_owner), m_cb(_cb) 17713513Sgabeblack@google.com { 17813513Sgabeblack@google.com sc_core::sc_spawn_options opts; 17913513Sgabeblack@google.com opts.spawn_method(); 18013513Sgabeblack@google.com opts.set_sensitivity(&m_e); 18113513Sgabeblack@google.com opts.dont_initialize(); 18213513Sgabeblack@google.com sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this), 18313513Sgabeblack@google.com sc_core::sc_gen_unique_name("fec"), &opts); 18413511Sgabeblack@google.com } 18513511Sgabeblack@google.com 18613513Sgabeblack@google.com peq_with_cb_and_phase(const char *_name, OWNER *_owner, cb _cb) : 18713513Sgabeblack@google.com sc_core::sc_object(_name), m_owner(_owner), m_cb(_cb) 18813513Sgabeblack@google.com { 18913513Sgabeblack@google.com sc_core::sc_spawn_options opts; 19013513Sgabeblack@google.com opts.spawn_method(); 19113513Sgabeblack@google.com opts.set_sensitivity(&m_e); 19213513Sgabeblack@google.com opts.dont_initialize(); 19313513Sgabeblack@google.com sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this), 19413513Sgabeblack@google.com sc_core::sc_gen_unique_name("fec"), &opts); 19513511Sgabeblack@google.com } 19613511Sgabeblack@google.com 19713513Sgabeblack@google.com ~peq_with_cb_and_phase() {} 19813513Sgabeblack@google.com 19913513Sgabeblack@google.com void 20013513Sgabeblack@google.com notify(tlm_payload_type &t, const tlm_phase_type &p, 20113513Sgabeblack@google.com const sc_core::sc_time &when) 20213513Sgabeblack@google.com { 20313513Sgabeblack@google.com if (when == sc_core::SC_ZERO_TIME) { 20413513Sgabeblack@google.com if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1) { 20513513Sgabeblack@google.com // Uneven delta cycle so delta delay is for even cycle. 20613513Sgabeblack@google.com m_even_delta.insert(PAYLOAD(&t,p)); 20713513Sgabeblack@google.com } else { 20813513Sgabeblack@google.com // Even delta cycle so delta delay is for uneven delta. 20913513Sgabeblack@google.com m_uneven_delta.insert(PAYLOAD(&t, p)); 21013513Sgabeblack@google.com } 21113513Sgabeblack@google.com m_e.notify(sc_core::SC_ZERO_TIME); 21213513Sgabeblack@google.com } else { 21313513Sgabeblack@google.com m_ppq.insert(PAYLOAD(&t, p), when + sc_core::sc_time_stamp()); 21413513Sgabeblack@google.com // Note, this will only overwrite the "newest" event. 21513513Sgabeblack@google.com m_e.notify(when); 21613513Sgabeblack@google.com } 21713511Sgabeblack@google.com } 21813511Sgabeblack@google.com 21913513Sgabeblack@google.com void 22013513Sgabeblack@google.com notify(tlm_payload_type &t, const tlm_phase_type &p) 22113513Sgabeblack@google.com { 22213513Sgabeblack@google.com m_immediate_yield.insert(PAYLOAD(&t, p)); 22313513Sgabeblack@google.com m_e.notify(); // Immediate notification. 22413511Sgabeblack@google.com } 22513511Sgabeblack@google.com 22613513Sgabeblack@google.com // Cancel all events from the event queue. 22713513Sgabeblack@google.com void 22813513Sgabeblack@google.com cancel_all() 22913513Sgabeblack@google.com { 23013513Sgabeblack@google.com m_ppq.reset(); 23113513Sgabeblack@google.com m_uneven_delta.reset(); 23213513Sgabeblack@google.com m_even_delta.reset(); 23313513Sgabeblack@google.com m_immediate_yield.reset(); 23413513Sgabeblack@google.com m_e.cancel(); 23513511Sgabeblack@google.com } 23613511Sgabeblack@google.com 23713513Sgabeblack@google.com private: 23813513Sgabeblack@google.com void 23913513Sgabeblack@google.com fec() 24013513Sgabeblack@google.com { 24113513Sgabeblack@google.com // Immediate yield notifications. 24213513Sgabeblack@google.com while (m_immediate_yield.next()) { 24313513Sgabeblack@google.com PAYLOAD &tmp = m_immediate_yield.get(); 24413513Sgabeblack@google.com (m_owner->*m_cb)(*tmp.first, tmp.second); 24513513Sgabeblack@google.com } 24613513Sgabeblack@google.com m_immediate_yield.reset(); 24713511Sgabeblack@google.com 24813513Sgabeblack@google.com // Delta notifications. 24913513Sgabeblack@google.com if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1) { 25013513Sgabeblack@google.com // Uneven delta so put out all payloads for uneven delta. 25113513Sgabeblack@google.com while (m_uneven_delta.next()) { 25213513Sgabeblack@google.com PAYLOAD &tmp = m_uneven_delta.get(); 25313513Sgabeblack@google.com (m_owner->*m_cb)(*tmp.first, tmp.second); 25413513Sgabeblack@google.com } 25513513Sgabeblack@google.com m_uneven_delta.reset(); 25613513Sgabeblack@google.com if (m_even_delta.size) 25713513Sgabeblack@google.com m_e.notify(sc_core::SC_ZERO_TIME); 25813513Sgabeblack@google.com } else { 25913513Sgabeblack@google.com while (m_even_delta.next()) { 26013513Sgabeblack@google.com PAYLOAD &tmp = m_even_delta.get(); 26113513Sgabeblack@google.com (m_owner->*m_cb)(*tmp.first, tmp.second); 26213513Sgabeblack@google.com } 26313513Sgabeblack@google.com m_even_delta.reset(); 26413513Sgabeblack@google.com if (m_uneven_delta.size) 26513513Sgabeblack@google.com m_e.notify(sc_core::SC_ZERO_TIME); 26613513Sgabeblack@google.com } 26713513Sgabeblack@google.com if (!m_ppq.get_size()) 26813513Sgabeblack@google.com return; // There were only delta notification. 26913511Sgabeblack@google.com 27013513Sgabeblack@google.com // Timed notifications. 27113513Sgabeblack@google.com const sc_core::sc_time now = sc_core::sc_time_stamp(); 27213513Sgabeblack@google.com sc_core::sc_time top = m_ppq.top_time(); 27313511Sgabeblack@google.com 27413513Sgabeblack@google.com while (m_ppq.get_size() && top == now) { 27513513Sgabeblack@google.com // Push all active ones into target. 27613513Sgabeblack@google.com PAYLOAD &tmp = m_ppq.top(); 27713513Sgabeblack@google.com (m_owner->*m_cb)(*tmp.first, tmp.second); 27813513Sgabeblack@google.com m_ppq.delete_top(); 27913513Sgabeblack@google.com top = m_ppq.top_time(); 28013513Sgabeblack@google.com } 28113513Sgabeblack@google.com if (m_ppq.get_size()) { 28213513Sgabeblack@google.com m_e.notify(top - now); 28313513Sgabeblack@google.com } 28413513Sgabeblack@google.com } 28513513Sgabeblack@google.com 28613513Sgabeblack@google.com OWNER *m_owner; 28713513Sgabeblack@google.com cb m_cb; 28813513Sgabeblack@google.com 28913513Sgabeblack@google.com time_ordered_list<PAYLOAD> m_ppq; 29013513Sgabeblack@google.com delta_list m_uneven_delta; 29113513Sgabeblack@google.com delta_list m_even_delta; 29213513Sgabeblack@google.com delta_list m_immediate_yield; 29313513Sgabeblack@google.com 29413513Sgabeblack@google.com sc_core::sc_event m_e; // Default event. 29513511Sgabeblack@google.com}; 29613511Sgabeblack@google.com 29713513Sgabeblack@google.com} // namespace tlm_utils 29813511Sgabeblack@google.com 29913513Sgabeblack@google.com#endif /* __SYSTEMC_EXT_TLM_UTILS_PEQ_WITH_CB_AND_PHASE_H__ */ 300