peq_with_cb_and_phase.h revision 13511
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 2013511Sgabeblack@google.com// 12-Jan-2009 John Aynsley Bug fix. Phase argument to notify should be const 2113511Sgabeblack@google.com// 20-Mar-2009 John Aynsley Add cancel_all() method 2213511Sgabeblack@google.com 2313511Sgabeblack@google.com 2413511Sgabeblack@google.com#ifndef __PEQ_WITH_CB_AND_PHASE_H__ 2513511Sgabeblack@google.com#define __PEQ_WITH_CB_AND_PHASE_H__ 2613511Sgabeblack@google.com 2713511Sgabeblack@google.com#ifndef SC_INCLUDE_DYNAMIC_PROCESSES // needed for sc_spawn 2813511Sgabeblack@google.com# define SC_INCLUDE_DYNAMIC_PROCESSES 2913511Sgabeblack@google.com#endif 3013511Sgabeblack@google.com 3113511Sgabeblack@google.com#include <vector> 3213511Sgabeblack@google.com#include <systemc> 3313511Sgabeblack@google.com#include <tlm> 3413511Sgabeblack@google.com 3513511Sgabeblack@google.comnamespace tlm_utils { 3613511Sgabeblack@google.com 3713511Sgabeblack@google.comtemplate <typename PAYLOAD> 3813511Sgabeblack@google.comclass time_ordered_list 3913511Sgabeblack@google.com{ 4013511Sgabeblack@google.compublic: 4113511Sgabeblack@google.com struct element 4213511Sgabeblack@google.com { 4313511Sgabeblack@google.com struct element *next; 4413511Sgabeblack@google.com PAYLOAD p; 4513511Sgabeblack@google.com sc_core::sc_time t; 4613511Sgabeblack@google.com sc_dt::uint64 d; 4713511Sgabeblack@google.com element(PAYLOAD& p, sc_core::sc_time t, sc_dt::uint64 d): p(p),t(t),d(d) {} 4813511Sgabeblack@google.com element(){} 4913511Sgabeblack@google.com }; 5013511Sgabeblack@google.com 5113511Sgabeblack@google.com element *nill; 5213511Sgabeblack@google.com element *empties; 5313511Sgabeblack@google.com element *list; 5413511Sgabeblack@google.com unsigned int size; 5513511Sgabeblack@google.com 5613511Sgabeblack@google.com time_ordered_list() 5713511Sgabeblack@google.com : nill(new element()), 5813511Sgabeblack@google.com empties(NULL), 5913511Sgabeblack@google.com list(nill), 6013511Sgabeblack@google.com size(0) 6113511Sgabeblack@google.com { 6213511Sgabeblack@google.com } 6313511Sgabeblack@google.com 6413511Sgabeblack@google.com ~time_ordered_list() { 6513511Sgabeblack@google.com reset(); 6613511Sgabeblack@google.com while(empties){ 6713511Sgabeblack@google.com struct element *e=empties->next; 6813511Sgabeblack@google.com delete empties; 6913511Sgabeblack@google.com empties=e; 7013511Sgabeblack@google.com } 7113511Sgabeblack@google.com delete nill; 7213511Sgabeblack@google.com } 7313511Sgabeblack@google.com 7413511Sgabeblack@google.com void reset() { 7513511Sgabeblack@google.com while(size) { 7613511Sgabeblack@google.com delete_top(); 7713511Sgabeblack@google.com } 7813511Sgabeblack@google.com } 7913511Sgabeblack@google.com 8013511Sgabeblack@google.com void insert(const PAYLOAD& p, sc_core::sc_time t) { 8113511Sgabeblack@google.com if (!empties) { 8213511Sgabeblack@google.com empties=new struct element(); 8313511Sgabeblack@google.com empties->next=NULL; 8413511Sgabeblack@google.com } 8513511Sgabeblack@google.com 8613511Sgabeblack@google.com struct element *e=empties; 8713511Sgabeblack@google.com empties=empties->next; 8813511Sgabeblack@google.com e->p=p; 8913511Sgabeblack@google.com e->t=t; 9013511Sgabeblack@google.com e->d=sc_core::sc_delta_count(); 9113511Sgabeblack@google.com 9213511Sgabeblack@google.com struct element * ancestor=nill; 9313511Sgabeblack@google.com struct element * iterator=list; 9413511Sgabeblack@google.com while (iterator!=nill && iterator->t<=t){ 9513511Sgabeblack@google.com ancestor=iterator; 9613511Sgabeblack@google.com iterator=iterator->next; 9713511Sgabeblack@google.com } 9813511Sgabeblack@google.com if (ancestor==nill){ 9913511Sgabeblack@google.com e->next=list; 10013511Sgabeblack@google.com list=e; 10113511Sgabeblack@google.com } 10213511Sgabeblack@google.com else { 10313511Sgabeblack@google.com e->next=iterator; 10413511Sgabeblack@google.com ancestor->next=e; 10513511Sgabeblack@google.com } 10613511Sgabeblack@google.com size++; 10713511Sgabeblack@google.com } 10813511Sgabeblack@google.com 10913511Sgabeblack@google.com void delete_top(){ 11013511Sgabeblack@google.com if (list != nill) { 11113511Sgabeblack@google.com struct element *e=list; 11213511Sgabeblack@google.com list=list->next; 11313511Sgabeblack@google.com e->next=empties; 11413511Sgabeblack@google.com empties=e; 11513511Sgabeblack@google.com size--; 11613511Sgabeblack@google.com } 11713511Sgabeblack@google.com } 11813511Sgabeblack@google.com 11913511Sgabeblack@google.com unsigned int get_size() 12013511Sgabeblack@google.com { 12113511Sgabeblack@google.com return size; 12213511Sgabeblack@google.com } 12313511Sgabeblack@google.com 12413511Sgabeblack@google.com PAYLOAD &top() 12513511Sgabeblack@google.com { 12613511Sgabeblack@google.com return list->p; 12713511Sgabeblack@google.com } 12813511Sgabeblack@google.com sc_core::sc_time top_time() 12913511Sgabeblack@google.com { 13013511Sgabeblack@google.com return list->t; 13113511Sgabeblack@google.com } 13213511Sgabeblack@google.com 13313511Sgabeblack@google.com sc_dt::uint64& top_delta() 13413511Sgabeblack@google.com { 13513511Sgabeblack@google.com return list->d; 13613511Sgabeblack@google.com } 13713511Sgabeblack@google.com 13813511Sgabeblack@google.com sc_core::sc_time next_time() 13913511Sgabeblack@google.com { 14013511Sgabeblack@google.com return list->next->t; 14113511Sgabeblack@google.com } 14213511Sgabeblack@google.com}; 14313511Sgabeblack@google.com 14413511Sgabeblack@google.com//--------------------------------------------------------------------------- 14513511Sgabeblack@google.com/** 14613511Sgabeblack@google.com * An event queue that can contain any number of pending 14713511Sgabeblack@google.com * notifications. Each notification have an associate payload. 14813511Sgabeblack@google.com */ 14913511Sgabeblack@google.com//--------------------------------------------------------------------------- 15013511Sgabeblack@google.comtemplate<typename OWNER,typename TYPES=tlm::tlm_base_protocol_types> 15113511Sgabeblack@google.comclass peq_with_cb_and_phase: 15213511Sgabeblack@google.com public sc_core::sc_object 15313511Sgabeblack@google.com{ 15413511Sgabeblack@google.com 15513511Sgabeblack@google.com typedef typename TYPES::tlm_payload_type tlm_payload_type; 15613511Sgabeblack@google.com typedef typename TYPES::tlm_phase_type tlm_phase_type; 15713511Sgabeblack@google.com typedef std::pair<tlm_payload_type*, tlm_phase_type> PAYLOAD; 15813511Sgabeblack@google.com typedef void (OWNER::*cb)(tlm_payload_type&, const tlm_phase_type&); 15913511Sgabeblack@google.com 16013511Sgabeblack@google.com class delta_list{ 16113511Sgabeblack@google.com public: 16213511Sgabeblack@google.com delta_list(){ 16313511Sgabeblack@google.com reset(); 16413511Sgabeblack@google.com entries.resize(100); 16513511Sgabeblack@google.com } 16613511Sgabeblack@google.com 16713511Sgabeblack@google.com inline void insert(const PAYLOAD& p){ 16813511Sgabeblack@google.com if (size==entries.size()){ 16913511Sgabeblack@google.com entries.resize(entries.size()*2); 17013511Sgabeblack@google.com } 17113511Sgabeblack@google.com entries[size++]=p; 17213511Sgabeblack@google.com } 17313511Sgabeblack@google.com 17413511Sgabeblack@google.com inline PAYLOAD& get(){ 17513511Sgabeblack@google.com return entries[out++]; 17613511Sgabeblack@google.com } 17713511Sgabeblack@google.com 17813511Sgabeblack@google.com inline bool next(){ 17913511Sgabeblack@google.com return out<size; 18013511Sgabeblack@google.com } 18113511Sgabeblack@google.com 18213511Sgabeblack@google.com inline void reset(){ 18313511Sgabeblack@google.com size=0; 18413511Sgabeblack@google.com out=0; 18513511Sgabeblack@google.com } 18613511Sgabeblack@google.com public: 18713511Sgabeblack@google.com unsigned int size; 18813511Sgabeblack@google.com private: 18913511Sgabeblack@google.com std::vector<PAYLOAD> entries; 19013511Sgabeblack@google.com unsigned int out; 19113511Sgabeblack@google.com }; 19213511Sgabeblack@google.com 19313511Sgabeblack@google.compublic: 19413511Sgabeblack@google.com 19513511Sgabeblack@google.com peq_with_cb_and_phase(OWNER* _owner, cb _cb) 19613511Sgabeblack@google.com :sc_core::sc_object( sc_core::sc_gen_unique_name( "peq_with_cb_and_phase" ) ) 19713511Sgabeblack@google.com ,m_owner(_owner) 19813511Sgabeblack@google.com ,m_cb(_cb) 19913511Sgabeblack@google.com { 20013511Sgabeblack@google.com sc_core::sc_spawn_options opts; 20113511Sgabeblack@google.com opts.spawn_method(); 20213511Sgabeblack@google.com opts.set_sensitivity(&m_e); 20313511Sgabeblack@google.com opts.dont_initialize(); 20413511Sgabeblack@google.com sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this), 20513511Sgabeblack@google.com sc_core::sc_gen_unique_name("fec"), &opts); 20613511Sgabeblack@google.com } 20713511Sgabeblack@google.com 20813511Sgabeblack@google.com peq_with_cb_and_phase(const char* _name, OWNER* _owner,cb _cb) 20913511Sgabeblack@google.com : sc_core::sc_object( _name ) 21013511Sgabeblack@google.com ,m_owner(_owner) 21113511Sgabeblack@google.com ,m_cb(_cb) 21213511Sgabeblack@google.com { 21313511Sgabeblack@google.com sc_core::sc_spawn_options opts; 21413511Sgabeblack@google.com opts.spawn_method(); 21513511Sgabeblack@google.com opts.set_sensitivity(&m_e); 21613511Sgabeblack@google.com opts.dont_initialize(); 21713511Sgabeblack@google.com sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this), 21813511Sgabeblack@google.com sc_core::sc_gen_unique_name("fec"), &opts); 21913511Sgabeblack@google.com } 22013511Sgabeblack@google.com 22113511Sgabeblack@google.com ~peq_with_cb_and_phase(){} 22213511Sgabeblack@google.com 22313511Sgabeblack@google.com void notify (tlm_payload_type& t, const tlm_phase_type& p, const sc_core::sc_time& when){ 22413511Sgabeblack@google.com //t.aquire(); 22513511Sgabeblack@google.com if (when==sc_core::SC_ZERO_TIME) { 22613511Sgabeblack@google.com if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1) //uneven delta cycle so delta delay is for even cylce 22713511Sgabeblack@google.com m_even_delta.insert(PAYLOAD(&t,p)); 22813511Sgabeblack@google.com else 22913511Sgabeblack@google.com m_uneven_delta.insert(PAYLOAD(&t,p)); //even delta cycle so delta delay is for uneven delta 23013511Sgabeblack@google.com m_e.notify(sc_core::SC_ZERO_TIME); 23113511Sgabeblack@google.com } 23213511Sgabeblack@google.com else { 23313511Sgabeblack@google.com m_ppq.insert(PAYLOAD(&t,p), when + sc_core::sc_time_stamp() ); 23413511Sgabeblack@google.com m_e.notify(when); // note, this will only over-right the "newest" event. 23513511Sgabeblack@google.com } 23613511Sgabeblack@google.com } 23713511Sgabeblack@google.com 23813511Sgabeblack@google.com void notify (tlm_payload_type& t, const tlm_phase_type& p){ 23913511Sgabeblack@google.com m_immediate_yield.insert(PAYLOAD(&t,p)); 24013511Sgabeblack@google.com m_e.notify(); // immediate notification 24113511Sgabeblack@google.com } 24213511Sgabeblack@google.com 24313511Sgabeblack@google.com // Cancel all events from the event queue 24413511Sgabeblack@google.com void cancel_all() { 24513511Sgabeblack@google.com m_ppq.reset(); 24613511Sgabeblack@google.com m_uneven_delta.reset(); 24713511Sgabeblack@google.com m_even_delta.reset(); 24813511Sgabeblack@google.com m_immediate_yield.reset(); 24913511Sgabeblack@google.com m_e.cancel(); 25013511Sgabeblack@google.com } 25113511Sgabeblack@google.com 25213511Sgabeblack@google.comprivate: 25313511Sgabeblack@google.com 25413511Sgabeblack@google.com void fec(){ 25513511Sgabeblack@google.com //immediate yield notifications 25613511Sgabeblack@google.com while(m_immediate_yield.next()) {PAYLOAD& tmp=m_immediate_yield.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();} 25713511Sgabeblack@google.com m_immediate_yield.reset(); 25813511Sgabeblack@google.com 25913511Sgabeblack@google.com //delta notifications 26013511Sgabeblack@google.com if (sc_core::sc_delta_count() & (sc_dt::uint64) 0x1) {//uneven delta so put out all payloads for uneven delta 26113511Sgabeblack@google.com while (m_uneven_delta.next()) {PAYLOAD& tmp=m_uneven_delta.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();} 26213511Sgabeblack@google.com m_uneven_delta.reset(); 26313511Sgabeblack@google.com if (m_even_delta.size) m_e.notify(sc_core::SC_ZERO_TIME); 26413511Sgabeblack@google.com } 26513511Sgabeblack@google.com else { 26613511Sgabeblack@google.com while (m_even_delta.next()) {PAYLOAD& tmp=m_even_delta.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();} 26713511Sgabeblack@google.com m_even_delta.reset(); 26813511Sgabeblack@google.com if (m_uneven_delta.size) m_e.notify(sc_core::SC_ZERO_TIME); 26913511Sgabeblack@google.com } 27013511Sgabeblack@google.com if (!m_ppq.get_size()) return; //there were only delta notification 27113511Sgabeblack@google.com 27213511Sgabeblack@google.com //timed notifications 27313511Sgabeblack@google.com const sc_core::sc_time now=sc_core::sc_time_stamp(); 27413511Sgabeblack@google.com sc_core::sc_time top=m_ppq.top_time(); 27513511Sgabeblack@google.com 27613511Sgabeblack@google.com while(m_ppq.get_size() && top==now) { // push all active ones into target 27713511Sgabeblack@google.com PAYLOAD& tmp=m_ppq.top(); 27813511Sgabeblack@google.com (m_owner->*m_cb)(*tmp.first, tmp.second); //tmp.first->release();} 27913511Sgabeblack@google.com m_ppq.delete_top(); 28013511Sgabeblack@google.com top=m_ppq.top_time(); 28113511Sgabeblack@google.com } 28213511Sgabeblack@google.com if ( m_ppq.get_size()) { 28313511Sgabeblack@google.com m_e.notify( top - now) ; 28413511Sgabeblack@google.com } 28513511Sgabeblack@google.com 28613511Sgabeblack@google.com } 28713511Sgabeblack@google.com 28813511Sgabeblack@google.com OWNER* m_owner; 28913511Sgabeblack@google.com cb m_cb; 29013511Sgabeblack@google.com 29113511Sgabeblack@google.com time_ordered_list<PAYLOAD> m_ppq; 29213511Sgabeblack@google.com delta_list m_uneven_delta; 29313511Sgabeblack@google.com delta_list m_even_delta; 29413511Sgabeblack@google.com delta_list m_immediate_yield; 29513511Sgabeblack@google.com 29613511Sgabeblack@google.com sc_core::sc_event m_e; // default event 29713511Sgabeblack@google.com}; 29813511Sgabeblack@google.com 29913511Sgabeblack@google.com} 30013511Sgabeblack@google.com 30113511Sgabeblack@google.com#endif // __PEQ_WITH_CB_AND_PHASE_H__ 302