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