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" 3013743Sgabeblack@google.com#include "../tlm_core/2/interfaces/fw_bw_ifs.hh" 3113586Sgabeblack@google.com 3213513Sgabeblack@google.comnamespace tlm_utils 3313513Sgabeblack@google.com{ 3413511Sgabeblack@google.com 3513511Sgabeblack@google.comtemplate <typename PAYLOAD> 3613511Sgabeblack@google.comclass time_ordered_list 3713511Sgabeblack@google.com{ 3813513Sgabeblack@google.com public: 3913513Sgabeblack@google.com struct element 4013513Sgabeblack@google.com { 4113513Sgabeblack@google.com struct element *next; 4213513Sgabeblack@google.com PAYLOAD p; 4313513Sgabeblack@google.com sc_core::sc_time t; 4413513Sgabeblack@google.com sc_dt::uint64 d; 4513513Sgabeblack@google.com element(PAYLOAD &p, sc_core::sc_time t, sc_dt::uint64 d) : 4613513Sgabeblack@google.com p(p), t(t), d(d) 4713513Sgabeblack@google.com {} 4813513Sgabeblack@google.com element() {} 4913513Sgabeblack@google.com }; 5013511Sgabeblack@google.com 5113513Sgabeblack@google.com element *nill; 5213513Sgabeblack@google.com element *empties; 5313513Sgabeblack@google.com element *list; 5413513Sgabeblack@google.com unsigned int size; 5513511Sgabeblack@google.com 5613513Sgabeblack@google.com time_ordered_list() : nill(new element()), empties(NULL), 5713513Sgabeblack@google.com list(nill), size(0) 5813513Sgabeblack@google.com {} 5913511Sgabeblack@google.com 6013513Sgabeblack@google.com ~time_ordered_list() 6113513Sgabeblack@google.com { 6213513Sgabeblack@google.com reset(); 6313513Sgabeblack@google.com while (empties) { 6413513Sgabeblack@google.com struct element *e = empties->next; 6513513Sgabeblack@google.com delete empties; 6613513Sgabeblack@google.com empties = e; 6713513Sgabeblack@google.com } 6813513Sgabeblack@google.com delete nill; 6913511Sgabeblack@google.com } 7013511Sgabeblack@google.com 7113513Sgabeblack@google.com void 7213513Sgabeblack@google.com reset() 7313513Sgabeblack@google.com { 7413513Sgabeblack@google.com while (size) { 7513513Sgabeblack@google.com delete_top(); 7613513Sgabeblack@google.com } 7713513Sgabeblack@google.com } 7813511Sgabeblack@google.com 7913513Sgabeblack@google.com void 8013513Sgabeblack@google.com insert(const PAYLOAD &p, sc_core::sc_time t) 8113513Sgabeblack@google.com { 8213513Sgabeblack@google.com if (!empties) { 8313513Sgabeblack@google.com empties = new struct element(); 8413513Sgabeblack@google.com empties->next=NULL; 8513513Sgabeblack@google.com } 8613513Sgabeblack@google.com 8713513Sgabeblack@google.com struct element *e = empties; 8813513Sgabeblack@google.com empties = empties->next; 8913513Sgabeblack@google.com e->p = p; 9013513Sgabeblack@google.com e->t = t; 9113513Sgabeblack@google.com e->d = sc_core::sc_delta_count(); 9213513Sgabeblack@google.com 9313513Sgabeblack@google.com struct element *ancestor = nill; 9413513Sgabeblack@google.com struct element *iterator = list; 9513513Sgabeblack@google.com while (iterator != nill && iterator->t <= t) { 9613513Sgabeblack@google.com ancestor = iterator; 9713513Sgabeblack@google.com iterator = iterator->next; 9813513Sgabeblack@google.com } 9913513Sgabeblack@google.com if (ancestor == nill) { 10013513Sgabeblack@google.com e->next = list; 10113513Sgabeblack@google.com list = e; 10213513Sgabeblack@google.com } else { 10313513Sgabeblack@google.com e->next = iterator; 10413513Sgabeblack@google.com ancestor->next = e; 10513513Sgabeblack@google.com } 10613513Sgabeblack@google.com size++; 10713511Sgabeblack@google.com } 10813513Sgabeblack@google.com 10913513Sgabeblack@google.com void 11013513Sgabeblack@google.com delete_top() 11113513Sgabeblack@google.com { 11213513Sgabeblack@google.com if (list != nill) { 11313513Sgabeblack@google.com struct element *e = list; 11413513Sgabeblack@google.com list = list->next; 11513513Sgabeblack@google.com e->next = empties; 11613513Sgabeblack@google.com empties = e; 11713513Sgabeblack@google.com size--; 11813513Sgabeblack@google.com } 11913511Sgabeblack@google.com } 12013511Sgabeblack@google.com 12113513Sgabeblack@google.com unsigned int get_size() { return size; } 12213513Sgabeblack@google.com PAYLOAD &top() { return list->p; } 12313513Sgabeblack@google.com sc_core::sc_time top_time() { return list->t; } 12413513Sgabeblack@google.com sc_dt::uint64 &top_delta() { return list->d; } 12513513Sgabeblack@google.com sc_core::sc_time next_time() { return list->next->t; } 12613511Sgabeblack@google.com}; 12713511Sgabeblack@google.com 12813511Sgabeblack@google.com//--------------------------------------------------------------------------- 12913511Sgabeblack@google.com/** 13013511Sgabeblack@google.com * An event queue that can contain any number of pending 13113511Sgabeblack@google.com * notifications. Each notification have an associate payload. 13213511Sgabeblack@google.com */ 13313511Sgabeblack@google.com//--------------------------------------------------------------------------- 13413513Sgabeblack@google.comtemplate<typename OWNER, typename TYPES=tlm::tlm_base_protocol_types> 13513513Sgabeblack@google.comclass peq_with_cb_and_phase : public sc_core::sc_object 13613511Sgabeblack@google.com{ 13713513Sgabeblack@google.com typedef typename TYPES::tlm_payload_type tlm_payload_type; 13813513Sgabeblack@google.com typedef typename TYPES::tlm_phase_type tlm_phase_type; 13913513Sgabeblack@google.com typedef std::pair<tlm_payload_type *, tlm_phase_type> PAYLOAD; 14013513Sgabeblack@google.com typedef void (OWNER::*cb)(tlm_payload_type &, const tlm_phase_type &); 14113511Sgabeblack@google.com 14213513Sgabeblack@google.com class delta_list 14313513Sgabeblack@google.com { 14413513Sgabeblack@google.com public: 14513513Sgabeblack@google.com delta_list() 14613513Sgabeblack@google.com { 14713513Sgabeblack@google.com reset(); 14813513Sgabeblack@google.com entries.resize(100); 14913513Sgabeblack@google.com } 15013511Sgabeblack@google.com 15113513Sgabeblack@google.com inline void 15213513Sgabeblack@google.com insert(const PAYLOAD &p) 15313513Sgabeblack@google.com { 15413513Sgabeblack@google.com if (size==entries.size()) { 15513513Sgabeblack@google.com entries.resize(entries.size() * 2); 15613513Sgabeblack@google.com } 15713513Sgabeblack@google.com entries[size++] = p; 15813513Sgabeblack@google.com } 15913513Sgabeblack@google.com 16013513Sgabeblack@google.com inline PAYLOAD &get() { return entries[out++]; } 16113513Sgabeblack@google.com inline bool next() { return out < size; } 16213513Sgabeblack@google.com inline void 16313513Sgabeblack@google.com reset() 16413513Sgabeblack@google.com { 16513513Sgabeblack@google.com size=0; 16613513Sgabeblack@google.com out=0; 16713513Sgabeblack@google.com } 16813513Sgabeblack@google.com 16913513Sgabeblack@google.com public: 17013513Sgabeblack@google.com unsigned int size; 17113513Sgabeblack@google.com 17213513Sgabeblack@google.com private: 17313513Sgabeblack@google.com std::vector<PAYLOAD> entries; 17413513Sgabeblack@google.com unsigned int out; 17513513Sgabeblack@google.com }; 17613513Sgabeblack@google.com 17713511Sgabeblack@google.com public: 17813513Sgabeblack@google.com peq_with_cb_and_phase(OWNER *_owner, cb _cb) : 17913513Sgabeblack@google.com sc_core::sc_object(sc_core::sc_gen_unique_name( 18013513Sgabeblack@google.com "peq_with_cb_and_phase")), 18113513Sgabeblack@google.com m_owner(_owner), m_cb(_cb) 18213513Sgabeblack@google.com { 18313513Sgabeblack@google.com sc_core::sc_spawn_options opts; 18413513Sgabeblack@google.com opts.spawn_method(); 18513513Sgabeblack@google.com opts.set_sensitivity(&m_e); 18613513Sgabeblack@google.com opts.dont_initialize(); 18713513Sgabeblack@google.com sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this), 18813513Sgabeblack@google.com sc_core::sc_gen_unique_name("fec"), &opts); 18913511Sgabeblack@google.com } 19013511Sgabeblack@google.com 19113513Sgabeblack@google.com peq_with_cb_and_phase(const char *_name, OWNER *_owner, cb _cb) : 19213513Sgabeblack@google.com sc_core::sc_object(_name), m_owner(_owner), m_cb(_cb) 19313513Sgabeblack@google.com { 19413513Sgabeblack@google.com sc_core::sc_spawn_options opts; 19513513Sgabeblack@google.com opts.spawn_method(); 19613513Sgabeblack@google.com opts.set_sensitivity(&m_e); 19713513Sgabeblack@google.com opts.dont_initialize(); 19813513Sgabeblack@google.com sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this), 19913513Sgabeblack@google.com sc_core::sc_gen_unique_name("fec"), &opts); 20013511Sgabeblack@google.com } 20113511Sgabeblack@google.com 20213513Sgabeblack@google.com ~peq_with_cb_and_phase() {} 20313513Sgabeblack@google.com 20413513Sgabeblack@google.com void 20513513Sgabeblack@google.com notify(tlm_payload_type &t, const tlm_phase_type &p, 20613513Sgabeblack@google.com const sc_core::sc_time &when) 20713513Sgabeblack@google.com { 20813513Sgabeblack@google.com if (when == sc_core::SC_ZERO_TIME) { 20913513Sgabeblack@google.com if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1) { 21013513Sgabeblack@google.com // Uneven delta cycle so delta delay is for even cycle. 21113513Sgabeblack@google.com m_even_delta.insert(PAYLOAD(&t,p)); 21213513Sgabeblack@google.com } else { 21313513Sgabeblack@google.com // Even delta cycle so delta delay is for uneven delta. 21413513Sgabeblack@google.com m_uneven_delta.insert(PAYLOAD(&t, p)); 21513513Sgabeblack@google.com } 21613513Sgabeblack@google.com m_e.notify(sc_core::SC_ZERO_TIME); 21713513Sgabeblack@google.com } else { 21813513Sgabeblack@google.com m_ppq.insert(PAYLOAD(&t, p), when + sc_core::sc_time_stamp()); 21913513Sgabeblack@google.com // Note, this will only overwrite the "newest" event. 22013513Sgabeblack@google.com m_e.notify(when); 22113513Sgabeblack@google.com } 22213511Sgabeblack@google.com } 22313511Sgabeblack@google.com 22413513Sgabeblack@google.com void 22513513Sgabeblack@google.com notify(tlm_payload_type &t, const tlm_phase_type &p) 22613513Sgabeblack@google.com { 22713513Sgabeblack@google.com m_immediate_yield.insert(PAYLOAD(&t, p)); 22813513Sgabeblack@google.com m_e.notify(); // Immediate notification. 22913511Sgabeblack@google.com } 23013511Sgabeblack@google.com 23113513Sgabeblack@google.com // Cancel all events from the event queue. 23213513Sgabeblack@google.com void 23313513Sgabeblack@google.com cancel_all() 23413513Sgabeblack@google.com { 23513513Sgabeblack@google.com m_ppq.reset(); 23613513Sgabeblack@google.com m_uneven_delta.reset(); 23713513Sgabeblack@google.com m_even_delta.reset(); 23813513Sgabeblack@google.com m_immediate_yield.reset(); 23913513Sgabeblack@google.com m_e.cancel(); 24013511Sgabeblack@google.com } 24113511Sgabeblack@google.com 24213513Sgabeblack@google.com private: 24313513Sgabeblack@google.com void 24413513Sgabeblack@google.com fec() 24513513Sgabeblack@google.com { 24613513Sgabeblack@google.com // Immediate yield notifications. 24713513Sgabeblack@google.com while (m_immediate_yield.next()) { 24813513Sgabeblack@google.com PAYLOAD &tmp = m_immediate_yield.get(); 24913513Sgabeblack@google.com (m_owner->*m_cb)(*tmp.first, tmp.second); 25013513Sgabeblack@google.com } 25113513Sgabeblack@google.com m_immediate_yield.reset(); 25213511Sgabeblack@google.com 25313513Sgabeblack@google.com // Delta notifications. 25413513Sgabeblack@google.com if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1) { 25513513Sgabeblack@google.com // Uneven delta so put out all payloads for uneven delta. 25613513Sgabeblack@google.com while (m_uneven_delta.next()) { 25713513Sgabeblack@google.com PAYLOAD &tmp = m_uneven_delta.get(); 25813513Sgabeblack@google.com (m_owner->*m_cb)(*tmp.first, tmp.second); 25913513Sgabeblack@google.com } 26013513Sgabeblack@google.com m_uneven_delta.reset(); 26113513Sgabeblack@google.com if (m_even_delta.size) 26213513Sgabeblack@google.com m_e.notify(sc_core::SC_ZERO_TIME); 26313513Sgabeblack@google.com } else { 26413513Sgabeblack@google.com while (m_even_delta.next()) { 26513513Sgabeblack@google.com PAYLOAD &tmp = m_even_delta.get(); 26613513Sgabeblack@google.com (m_owner->*m_cb)(*tmp.first, tmp.second); 26713513Sgabeblack@google.com } 26813513Sgabeblack@google.com m_even_delta.reset(); 26913513Sgabeblack@google.com if (m_uneven_delta.size) 27013513Sgabeblack@google.com m_e.notify(sc_core::SC_ZERO_TIME); 27113513Sgabeblack@google.com } 27213513Sgabeblack@google.com if (!m_ppq.get_size()) 27313513Sgabeblack@google.com return; // There were only delta notification. 27413511Sgabeblack@google.com 27513513Sgabeblack@google.com // Timed notifications. 27613513Sgabeblack@google.com const sc_core::sc_time now = sc_core::sc_time_stamp(); 27713513Sgabeblack@google.com sc_core::sc_time top = m_ppq.top_time(); 27813511Sgabeblack@google.com 27913513Sgabeblack@google.com while (m_ppq.get_size() && top == now) { 28013513Sgabeblack@google.com // Push all active ones into target. 28113513Sgabeblack@google.com PAYLOAD &tmp = m_ppq.top(); 28213513Sgabeblack@google.com (m_owner->*m_cb)(*tmp.first, tmp.second); 28313513Sgabeblack@google.com m_ppq.delete_top(); 28413513Sgabeblack@google.com top = m_ppq.top_time(); 28513513Sgabeblack@google.com } 28613513Sgabeblack@google.com if (m_ppq.get_size()) { 28713513Sgabeblack@google.com m_e.notify(top - now); 28813513Sgabeblack@google.com } 28913513Sgabeblack@google.com } 29013513Sgabeblack@google.com 29113513Sgabeblack@google.com OWNER *m_owner; 29213513Sgabeblack@google.com cb m_cb; 29313513Sgabeblack@google.com 29413513Sgabeblack@google.com time_ordered_list<PAYLOAD> m_ppq; 29513513Sgabeblack@google.com delta_list m_uneven_delta; 29613513Sgabeblack@google.com delta_list m_even_delta; 29713513Sgabeblack@google.com delta_list m_immediate_yield; 29813513Sgabeblack@google.com 29913513Sgabeblack@google.com sc_core::sc_event m_e; // Default event. 30013511Sgabeblack@google.com}; 30113511Sgabeblack@google.com 30213513Sgabeblack@google.com} // namespace tlm_utils 30313511Sgabeblack@google.com 30413513Sgabeblack@google.com#endif /* __SYSTEMC_EXT_TLM_UTILS_PEQ_WITH_CB_AND_PHASE_H__ */ 305