peq_with_cb_and_phase.h revision 13586
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 2313513Sgabeblack@google.com#include <vector> 2413511Sgabeblack@google.com 2513586Sgabeblack@google.com#include "../core/sc_main.hh" 2613586Sgabeblack@google.com#include "../core/sc_object.hh" 2713586Sgabeblack@google.com#include "../core/sc_spawn.hh" 2813586Sgabeblack@google.com#include "../core/sc_time.hh" 2913586Sgabeblack@google.com#include "../dt/int/sc_nbdefs.hh" 3013586Sgabeblack@google.com 3113513Sgabeblack@google.comnamespace tlm_utils 3213513Sgabeblack@google.com{ 3313511Sgabeblack@google.com 3413511Sgabeblack@google.comtemplate <typename PAYLOAD> 3513511Sgabeblack@google.comclass time_ordered_list 3613511Sgabeblack@google.com{ 3713513Sgabeblack@google.com public: 3813513Sgabeblack@google.com struct element 3913513Sgabeblack@google.com { 4013513Sgabeblack@google.com struct element *next; 4113513Sgabeblack@google.com PAYLOAD p; 4213513Sgabeblack@google.com sc_core::sc_time t; 4313513Sgabeblack@google.com sc_dt::uint64 d; 4413513Sgabeblack@google.com element(PAYLOAD &p, sc_core::sc_time t, sc_dt::uint64 d) : 4513513Sgabeblack@google.com p(p), t(t), d(d) 4613513Sgabeblack@google.com {} 4713513Sgabeblack@google.com element() {} 4813513Sgabeblack@google.com }; 4913511Sgabeblack@google.com 5013513Sgabeblack@google.com element *nill; 5113513Sgabeblack@google.com element *empties; 5213513Sgabeblack@google.com element *list; 5313513Sgabeblack@google.com unsigned int size; 5413511Sgabeblack@google.com 5513513Sgabeblack@google.com time_ordered_list() : nill(new element()), empties(NULL), 5613513Sgabeblack@google.com list(nill), size(0) 5713513Sgabeblack@google.com {} 5813511Sgabeblack@google.com 5913513Sgabeblack@google.com ~time_ordered_list() 6013513Sgabeblack@google.com { 6113513Sgabeblack@google.com reset(); 6213513Sgabeblack@google.com while (empties) { 6313513Sgabeblack@google.com struct element *e = empties->next; 6413513Sgabeblack@google.com delete empties; 6513513Sgabeblack@google.com empties = e; 6613513Sgabeblack@google.com } 6713513Sgabeblack@google.com delete nill; 6813511Sgabeblack@google.com } 6913511Sgabeblack@google.com 7013513Sgabeblack@google.com void 7113513Sgabeblack@google.com reset() 7213513Sgabeblack@google.com { 7313513Sgabeblack@google.com while (size) { 7413513Sgabeblack@google.com delete_top(); 7513513Sgabeblack@google.com } 7613513Sgabeblack@google.com } 7713511Sgabeblack@google.com 7813513Sgabeblack@google.com void 7913513Sgabeblack@google.com insert(const PAYLOAD &p, sc_core::sc_time t) 8013513Sgabeblack@google.com { 8113513Sgabeblack@google.com if (!empties) { 8213513Sgabeblack@google.com empties = new struct element(); 8313513Sgabeblack@google.com empties->next=NULL; 8413513Sgabeblack@google.com } 8513513Sgabeblack@google.com 8613513Sgabeblack@google.com struct element *e = empties; 8713513Sgabeblack@google.com empties = empties->next; 8813513Sgabeblack@google.com e->p = p; 8913513Sgabeblack@google.com e->t = t; 9013513Sgabeblack@google.com e->d = sc_core::sc_delta_count(); 9113513Sgabeblack@google.com 9213513Sgabeblack@google.com struct element *ancestor = nill; 9313513Sgabeblack@google.com struct element *iterator = list; 9413513Sgabeblack@google.com while (iterator != nill && iterator->t <= t) { 9513513Sgabeblack@google.com ancestor = iterator; 9613513Sgabeblack@google.com iterator = iterator->next; 9713513Sgabeblack@google.com } 9813513Sgabeblack@google.com if (ancestor == nill) { 9913513Sgabeblack@google.com e->next = list; 10013513Sgabeblack@google.com list = e; 10113513Sgabeblack@google.com } else { 10213513Sgabeblack@google.com e->next = iterator; 10313513Sgabeblack@google.com ancestor->next = e; 10413513Sgabeblack@google.com } 10513513Sgabeblack@google.com size++; 10613511Sgabeblack@google.com } 10713513Sgabeblack@google.com 10813513Sgabeblack@google.com void 10913513Sgabeblack@google.com delete_top() 11013513Sgabeblack@google.com { 11113513Sgabeblack@google.com if (list != nill) { 11213513Sgabeblack@google.com struct element *e = list; 11313513Sgabeblack@google.com list = list->next; 11413513Sgabeblack@google.com e->next = empties; 11513513Sgabeblack@google.com empties = e; 11613513Sgabeblack@google.com size--; 11713513Sgabeblack@google.com } 11813511Sgabeblack@google.com } 11913511Sgabeblack@google.com 12013513Sgabeblack@google.com unsigned int get_size() { return size; } 12113513Sgabeblack@google.com PAYLOAD &top() { return list->p; } 12213513Sgabeblack@google.com sc_core::sc_time top_time() { return list->t; } 12313513Sgabeblack@google.com sc_dt::uint64 &top_delta() { return list->d; } 12413513Sgabeblack@google.com sc_core::sc_time next_time() { return list->next->t; } 12513511Sgabeblack@google.com}; 12613511Sgabeblack@google.com 12713511Sgabeblack@google.com//--------------------------------------------------------------------------- 12813511Sgabeblack@google.com/** 12913511Sgabeblack@google.com * An event queue that can contain any number of pending 13013511Sgabeblack@google.com * notifications. Each notification have an associate payload. 13113511Sgabeblack@google.com */ 13213511Sgabeblack@google.com//--------------------------------------------------------------------------- 13313513Sgabeblack@google.comtemplate<typename OWNER, typename TYPES=tlm::tlm_base_protocol_types> 13413513Sgabeblack@google.comclass peq_with_cb_and_phase : public sc_core::sc_object 13513511Sgabeblack@google.com{ 13613513Sgabeblack@google.com typedef typename TYPES::tlm_payload_type tlm_payload_type; 13713513Sgabeblack@google.com typedef typename TYPES::tlm_phase_type tlm_phase_type; 13813513Sgabeblack@google.com typedef std::pair<tlm_payload_type *, tlm_phase_type> PAYLOAD; 13913513Sgabeblack@google.com typedef void (OWNER::*cb)(tlm_payload_type &, const tlm_phase_type &); 14013511Sgabeblack@google.com 14113513Sgabeblack@google.com class delta_list 14213513Sgabeblack@google.com { 14313513Sgabeblack@google.com public: 14413513Sgabeblack@google.com delta_list() 14513513Sgabeblack@google.com { 14613513Sgabeblack@google.com reset(); 14713513Sgabeblack@google.com entries.resize(100); 14813513Sgabeblack@google.com } 14913511Sgabeblack@google.com 15013513Sgabeblack@google.com inline void 15113513Sgabeblack@google.com insert(const PAYLOAD &p) 15213513Sgabeblack@google.com { 15313513Sgabeblack@google.com if (size==entries.size()) { 15413513Sgabeblack@google.com entries.resize(entries.size() * 2); 15513513Sgabeblack@google.com } 15613513Sgabeblack@google.com entries[size++] = p; 15713513Sgabeblack@google.com } 15813513Sgabeblack@google.com 15913513Sgabeblack@google.com inline PAYLOAD &get() { return entries[out++]; } 16013513Sgabeblack@google.com inline bool next() { return out < size; } 16113513Sgabeblack@google.com inline void 16213513Sgabeblack@google.com reset() 16313513Sgabeblack@google.com { 16413513Sgabeblack@google.com size=0; 16513513Sgabeblack@google.com out=0; 16613513Sgabeblack@google.com } 16713513Sgabeblack@google.com 16813513Sgabeblack@google.com public: 16913513Sgabeblack@google.com unsigned int size; 17013513Sgabeblack@google.com 17113513Sgabeblack@google.com private: 17213513Sgabeblack@google.com std::vector<PAYLOAD> entries; 17313513Sgabeblack@google.com unsigned int out; 17413513Sgabeblack@google.com }; 17513513Sgabeblack@google.com 17613511Sgabeblack@google.com public: 17713513Sgabeblack@google.com peq_with_cb_and_phase(OWNER *_owner, cb _cb) : 17813513Sgabeblack@google.com sc_core::sc_object(sc_core::sc_gen_unique_name( 17913513Sgabeblack@google.com "peq_with_cb_and_phase")), 18013513Sgabeblack@google.com m_owner(_owner), m_cb(_cb) 18113513Sgabeblack@google.com { 18213513Sgabeblack@google.com sc_core::sc_spawn_options opts; 18313513Sgabeblack@google.com opts.spawn_method(); 18413513Sgabeblack@google.com opts.set_sensitivity(&m_e); 18513513Sgabeblack@google.com opts.dont_initialize(); 18613513Sgabeblack@google.com sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this), 18713513Sgabeblack@google.com sc_core::sc_gen_unique_name("fec"), &opts); 18813511Sgabeblack@google.com } 18913511Sgabeblack@google.com 19013513Sgabeblack@google.com peq_with_cb_and_phase(const char *_name, OWNER *_owner, cb _cb) : 19113513Sgabeblack@google.com sc_core::sc_object(_name), m_owner(_owner), m_cb(_cb) 19213513Sgabeblack@google.com { 19313513Sgabeblack@google.com sc_core::sc_spawn_options opts; 19413513Sgabeblack@google.com opts.spawn_method(); 19513513Sgabeblack@google.com opts.set_sensitivity(&m_e); 19613513Sgabeblack@google.com opts.dont_initialize(); 19713513Sgabeblack@google.com sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this), 19813513Sgabeblack@google.com sc_core::sc_gen_unique_name("fec"), &opts); 19913511Sgabeblack@google.com } 20013511Sgabeblack@google.com 20113513Sgabeblack@google.com ~peq_with_cb_and_phase() {} 20213513Sgabeblack@google.com 20313513Sgabeblack@google.com void 20413513Sgabeblack@google.com notify(tlm_payload_type &t, const tlm_phase_type &p, 20513513Sgabeblack@google.com const sc_core::sc_time &when) 20613513Sgabeblack@google.com { 20713513Sgabeblack@google.com if (when == sc_core::SC_ZERO_TIME) { 20813513Sgabeblack@google.com if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1) { 20913513Sgabeblack@google.com // Uneven delta cycle so delta delay is for even cycle. 21013513Sgabeblack@google.com m_even_delta.insert(PAYLOAD(&t,p)); 21113513Sgabeblack@google.com } else { 21213513Sgabeblack@google.com // Even delta cycle so delta delay is for uneven delta. 21313513Sgabeblack@google.com m_uneven_delta.insert(PAYLOAD(&t, p)); 21413513Sgabeblack@google.com } 21513513Sgabeblack@google.com m_e.notify(sc_core::SC_ZERO_TIME); 21613513Sgabeblack@google.com } else { 21713513Sgabeblack@google.com m_ppq.insert(PAYLOAD(&t, p), when + sc_core::sc_time_stamp()); 21813513Sgabeblack@google.com // Note, this will only overwrite the "newest" event. 21913513Sgabeblack@google.com m_e.notify(when); 22013513Sgabeblack@google.com } 22113511Sgabeblack@google.com } 22213511Sgabeblack@google.com 22313513Sgabeblack@google.com void 22413513Sgabeblack@google.com notify(tlm_payload_type &t, const tlm_phase_type &p) 22513513Sgabeblack@google.com { 22613513Sgabeblack@google.com m_immediate_yield.insert(PAYLOAD(&t, p)); 22713513Sgabeblack@google.com m_e.notify(); // Immediate notification. 22813511Sgabeblack@google.com } 22913511Sgabeblack@google.com 23013513Sgabeblack@google.com // Cancel all events from the event queue. 23113513Sgabeblack@google.com void 23213513Sgabeblack@google.com cancel_all() 23313513Sgabeblack@google.com { 23413513Sgabeblack@google.com m_ppq.reset(); 23513513Sgabeblack@google.com m_uneven_delta.reset(); 23613513Sgabeblack@google.com m_even_delta.reset(); 23713513Sgabeblack@google.com m_immediate_yield.reset(); 23813513Sgabeblack@google.com m_e.cancel(); 23913511Sgabeblack@google.com } 24013511Sgabeblack@google.com 24113513Sgabeblack@google.com private: 24213513Sgabeblack@google.com void 24313513Sgabeblack@google.com fec() 24413513Sgabeblack@google.com { 24513513Sgabeblack@google.com // Immediate yield notifications. 24613513Sgabeblack@google.com while (m_immediate_yield.next()) { 24713513Sgabeblack@google.com PAYLOAD &tmp = m_immediate_yield.get(); 24813513Sgabeblack@google.com (m_owner->*m_cb)(*tmp.first, tmp.second); 24913513Sgabeblack@google.com } 25013513Sgabeblack@google.com m_immediate_yield.reset(); 25113511Sgabeblack@google.com 25213513Sgabeblack@google.com // Delta notifications. 25313513Sgabeblack@google.com if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1) { 25413513Sgabeblack@google.com // Uneven delta so put out all payloads for uneven delta. 25513513Sgabeblack@google.com while (m_uneven_delta.next()) { 25613513Sgabeblack@google.com PAYLOAD &tmp = m_uneven_delta.get(); 25713513Sgabeblack@google.com (m_owner->*m_cb)(*tmp.first, tmp.second); 25813513Sgabeblack@google.com } 25913513Sgabeblack@google.com m_uneven_delta.reset(); 26013513Sgabeblack@google.com if (m_even_delta.size) 26113513Sgabeblack@google.com m_e.notify(sc_core::SC_ZERO_TIME); 26213513Sgabeblack@google.com } else { 26313513Sgabeblack@google.com while (m_even_delta.next()) { 26413513Sgabeblack@google.com PAYLOAD &tmp = m_even_delta.get(); 26513513Sgabeblack@google.com (m_owner->*m_cb)(*tmp.first, tmp.second); 26613513Sgabeblack@google.com } 26713513Sgabeblack@google.com m_even_delta.reset(); 26813513Sgabeblack@google.com if (m_uneven_delta.size) 26913513Sgabeblack@google.com m_e.notify(sc_core::SC_ZERO_TIME); 27013513Sgabeblack@google.com } 27113513Sgabeblack@google.com if (!m_ppq.get_size()) 27213513Sgabeblack@google.com return; // There were only delta notification. 27313511Sgabeblack@google.com 27413513Sgabeblack@google.com // Timed notifications. 27513513Sgabeblack@google.com const sc_core::sc_time now = sc_core::sc_time_stamp(); 27613513Sgabeblack@google.com sc_core::sc_time top = m_ppq.top_time(); 27713511Sgabeblack@google.com 27813513Sgabeblack@google.com while (m_ppq.get_size() && top == now) { 27913513Sgabeblack@google.com // Push all active ones into target. 28013513Sgabeblack@google.com PAYLOAD &tmp = m_ppq.top(); 28113513Sgabeblack@google.com (m_owner->*m_cb)(*tmp.first, tmp.second); 28213513Sgabeblack@google.com m_ppq.delete_top(); 28313513Sgabeblack@google.com top = m_ppq.top_time(); 28413513Sgabeblack@google.com } 28513513Sgabeblack@google.com if (m_ppq.get_size()) { 28613513Sgabeblack@google.com m_e.notify(top - now); 28713513Sgabeblack@google.com } 28813513Sgabeblack@google.com } 28913513Sgabeblack@google.com 29013513Sgabeblack@google.com OWNER *m_owner; 29113513Sgabeblack@google.com cb m_cb; 29213513Sgabeblack@google.com 29313513Sgabeblack@google.com time_ordered_list<PAYLOAD> m_ppq; 29413513Sgabeblack@google.com delta_list m_uneven_delta; 29513513Sgabeblack@google.com delta_list m_even_delta; 29613513Sgabeblack@google.com delta_list m_immediate_yield; 29713513Sgabeblack@google.com 29813513Sgabeblack@google.com sc_core::sc_event m_e; // Default event. 29913511Sgabeblack@google.com}; 30013511Sgabeblack@google.com 30113513Sgabeblack@google.com} // namespace tlm_utils 30213511Sgabeblack@google.com 30313513Sgabeblack@google.com#endif /* __SYSTEMC_EXT_TLM_UTILS_PEQ_WITH_CB_AND_PHASE_H__ */ 304