112027Sjungma@eit.uni-kl.de/*****************************************************************************
212027Sjungma@eit.uni-kl.de
312027Sjungma@eit.uni-kl.de  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
412027Sjungma@eit.uni-kl.de  more contributor license agreements.  See the NOTICE file distributed
512027Sjungma@eit.uni-kl.de  with this work for additional information regarding copyright ownership.
612027Sjungma@eit.uni-kl.de  Accellera licenses this file to you under the Apache License, Version 2.0
712027Sjungma@eit.uni-kl.de  (the "License"); you may not use this file except in compliance with the
812027Sjungma@eit.uni-kl.de  License.  You may obtain a copy of the License at
912027Sjungma@eit.uni-kl.de
1012027Sjungma@eit.uni-kl.de    http://www.apache.org/licenses/LICENSE-2.0
1112027Sjungma@eit.uni-kl.de
1212027Sjungma@eit.uni-kl.de  Unless required by applicable law or agreed to in writing, software
1312027Sjungma@eit.uni-kl.de  distributed under the License is distributed on an "AS IS" BASIS,
1412027Sjungma@eit.uni-kl.de  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1512027Sjungma@eit.uni-kl.de  implied.  See the License for the specific language governing
1612027Sjungma@eit.uni-kl.de  permissions and limitations under the License.
1712027Sjungma@eit.uni-kl.de
1812027Sjungma@eit.uni-kl.de *****************************************************************************/
1912027Sjungma@eit.uni-kl.de
2012027Sjungma@eit.uni-kl.de// 12-Jan-2009  John Aynsley  Bug fix. Phase argument to notify should be const
2112027Sjungma@eit.uni-kl.de// 20-Mar-2009  John Aynsley  Add cancel_all() method
2212027Sjungma@eit.uni-kl.de
2312027Sjungma@eit.uni-kl.de
2412027Sjungma@eit.uni-kl.de#ifndef __PEQ_WITH_CB_AND_PHASE_H__
2512027Sjungma@eit.uni-kl.de#define __PEQ_WITH_CB_AND_PHASE_H__
2612027Sjungma@eit.uni-kl.de
2712027Sjungma@eit.uni-kl.de#ifndef SC_INCLUDE_DYNAMIC_PROCESSES // needed for sc_spawn
2812027Sjungma@eit.uni-kl.de#  define SC_INCLUDE_DYNAMIC_PROCESSES
2912027Sjungma@eit.uni-kl.de#endif
3012027Sjungma@eit.uni-kl.de
3112027Sjungma@eit.uni-kl.de#include <vector>
3212027Sjungma@eit.uni-kl.de#include <systemc>
3312027Sjungma@eit.uni-kl.de#include <tlm>
3412027Sjungma@eit.uni-kl.de
3512027Sjungma@eit.uni-kl.denamespace tlm_utils {
3612027Sjungma@eit.uni-kl.de
3712027Sjungma@eit.uni-kl.detemplate <typename PAYLOAD>
3812027Sjungma@eit.uni-kl.declass time_ordered_list
3912027Sjungma@eit.uni-kl.de{
4012027Sjungma@eit.uni-kl.depublic:
4112027Sjungma@eit.uni-kl.de  struct element
4212027Sjungma@eit.uni-kl.de  {
4312027Sjungma@eit.uni-kl.de    struct element  *next;
4412027Sjungma@eit.uni-kl.de    PAYLOAD p;
4512027Sjungma@eit.uni-kl.de    sc_core::sc_time t;
4612027Sjungma@eit.uni-kl.de    sc_dt::uint64 d;
4712027Sjungma@eit.uni-kl.de    element(PAYLOAD& p, sc_core::sc_time t, sc_dt::uint64 d): p(p),t(t),d(d) {}
4812027Sjungma@eit.uni-kl.de    element(){}
4912027Sjungma@eit.uni-kl.de  };
5012027Sjungma@eit.uni-kl.de
5112027Sjungma@eit.uni-kl.de  element *nill;
5212027Sjungma@eit.uni-kl.de  element *empties;
5312027Sjungma@eit.uni-kl.de  element *list;
5412027Sjungma@eit.uni-kl.de  unsigned int size;
5512027Sjungma@eit.uni-kl.de
5612027Sjungma@eit.uni-kl.de  time_ordered_list()
5712027Sjungma@eit.uni-kl.de    : nill(new element()),
5812027Sjungma@eit.uni-kl.de      empties(NULL),
5912027Sjungma@eit.uni-kl.de      list(nill),
6012027Sjungma@eit.uni-kl.de      size(0)
6112027Sjungma@eit.uni-kl.de  {
6212027Sjungma@eit.uni-kl.de  }
6312027Sjungma@eit.uni-kl.de
6412027Sjungma@eit.uni-kl.de  ~time_ordered_list() {
6512027Sjungma@eit.uni-kl.de    reset();
6612027Sjungma@eit.uni-kl.de    while(empties){
6712027Sjungma@eit.uni-kl.de      struct element *e=empties->next;
6812027Sjungma@eit.uni-kl.de      delete empties;
6912027Sjungma@eit.uni-kl.de      empties=e;
7012027Sjungma@eit.uni-kl.de    }
7112027Sjungma@eit.uni-kl.de    delete nill;
7212027Sjungma@eit.uni-kl.de  }
7312027Sjungma@eit.uni-kl.de
7412027Sjungma@eit.uni-kl.de  void reset() {
7512027Sjungma@eit.uni-kl.de    while(size) {
7612027Sjungma@eit.uni-kl.de      delete_top();
7712027Sjungma@eit.uni-kl.de    }
7812027Sjungma@eit.uni-kl.de  }
7912027Sjungma@eit.uni-kl.de
8012027Sjungma@eit.uni-kl.de  void insert(const PAYLOAD& p, sc_core::sc_time t) {
8112027Sjungma@eit.uni-kl.de    if (!empties) {
8212027Sjungma@eit.uni-kl.de      empties=new struct element();
8312027Sjungma@eit.uni-kl.de      empties->next=NULL;
8412027Sjungma@eit.uni-kl.de    }
8512027Sjungma@eit.uni-kl.de
8612027Sjungma@eit.uni-kl.de    struct element *e=empties;
8712027Sjungma@eit.uni-kl.de    empties=empties->next;
8812027Sjungma@eit.uni-kl.de    e->p=p;
8912027Sjungma@eit.uni-kl.de    e->t=t;
9012027Sjungma@eit.uni-kl.de    e->d=sc_core::sc_delta_count();
9112027Sjungma@eit.uni-kl.de
9212027Sjungma@eit.uni-kl.de    struct element * ancestor=nill;
9312027Sjungma@eit.uni-kl.de    struct element * iterator=list;
9412027Sjungma@eit.uni-kl.de    while (iterator!=nill && iterator->t<=t){
9512027Sjungma@eit.uni-kl.de      ancestor=iterator;
9612027Sjungma@eit.uni-kl.de      iterator=iterator->next;
9712027Sjungma@eit.uni-kl.de    }
9812027Sjungma@eit.uni-kl.de    if (ancestor==nill){
9912027Sjungma@eit.uni-kl.de      e->next=list;
10012027Sjungma@eit.uni-kl.de      list=e;
10112027Sjungma@eit.uni-kl.de    }
10212027Sjungma@eit.uni-kl.de    else {
10312027Sjungma@eit.uni-kl.de      e->next=iterator;
10412027Sjungma@eit.uni-kl.de      ancestor->next=e;
10512027Sjungma@eit.uni-kl.de    }
10612027Sjungma@eit.uni-kl.de    size++;
10712027Sjungma@eit.uni-kl.de  }
10812027Sjungma@eit.uni-kl.de
10912027Sjungma@eit.uni-kl.de  void delete_top(){
11012027Sjungma@eit.uni-kl.de    if (list != nill) {
11112027Sjungma@eit.uni-kl.de      struct element *e=list;
11212027Sjungma@eit.uni-kl.de      list=list->next;
11312027Sjungma@eit.uni-kl.de      e->next=empties;
11412027Sjungma@eit.uni-kl.de      empties=e;
11512027Sjungma@eit.uni-kl.de      size--;
11612027Sjungma@eit.uni-kl.de    }
11712027Sjungma@eit.uni-kl.de  }
11812027Sjungma@eit.uni-kl.de
11912027Sjungma@eit.uni-kl.de  unsigned int get_size()
12012027Sjungma@eit.uni-kl.de  {
12112027Sjungma@eit.uni-kl.de    return size;
12212027Sjungma@eit.uni-kl.de  }
12312027Sjungma@eit.uni-kl.de
12412027Sjungma@eit.uni-kl.de  PAYLOAD &top()
12512027Sjungma@eit.uni-kl.de  {
12612027Sjungma@eit.uni-kl.de    return list->p;
12712027Sjungma@eit.uni-kl.de  }
12812027Sjungma@eit.uni-kl.de  sc_core::sc_time top_time()
12912027Sjungma@eit.uni-kl.de  {
13012027Sjungma@eit.uni-kl.de    return list->t;
13112027Sjungma@eit.uni-kl.de  }
13212027Sjungma@eit.uni-kl.de
13312027Sjungma@eit.uni-kl.de  sc_dt::uint64& top_delta()
13412027Sjungma@eit.uni-kl.de  {
13512027Sjungma@eit.uni-kl.de    return list->d;
13612027Sjungma@eit.uni-kl.de  }
13712027Sjungma@eit.uni-kl.de
13812027Sjungma@eit.uni-kl.de  sc_core::sc_time next_time()
13912027Sjungma@eit.uni-kl.de  {
14012027Sjungma@eit.uni-kl.de    return list->next->t;
14112027Sjungma@eit.uni-kl.de  }
14212027Sjungma@eit.uni-kl.de};
14312027Sjungma@eit.uni-kl.de
14412027Sjungma@eit.uni-kl.de//---------------------------------------------------------------------------
14512027Sjungma@eit.uni-kl.de/**
14612027Sjungma@eit.uni-kl.de * An event queue that can contain any number of pending
14712027Sjungma@eit.uni-kl.de * notifications. Each notification have an associate payload.
14812027Sjungma@eit.uni-kl.de */
14912027Sjungma@eit.uni-kl.de//---------------------------------------------------------------------------
15012027Sjungma@eit.uni-kl.detemplate<typename OWNER,typename TYPES=tlm::tlm_base_protocol_types>
15112027Sjungma@eit.uni-kl.declass peq_with_cb_and_phase:
15212027Sjungma@eit.uni-kl.de  public sc_core::sc_object
15312027Sjungma@eit.uni-kl.de{
15412027Sjungma@eit.uni-kl.de
15512027Sjungma@eit.uni-kl.de  typedef typename TYPES::tlm_payload_type tlm_payload_type;
15612027Sjungma@eit.uni-kl.de  typedef typename TYPES::tlm_phase_type   tlm_phase_type;
15712027Sjungma@eit.uni-kl.de  typedef std::pair<tlm_payload_type*, tlm_phase_type> PAYLOAD;
15812027Sjungma@eit.uni-kl.de  typedef void (OWNER::*cb)(tlm_payload_type&, const tlm_phase_type&);
15912027Sjungma@eit.uni-kl.de
16012027Sjungma@eit.uni-kl.de  class delta_list{
16112027Sjungma@eit.uni-kl.de  public:
16212027Sjungma@eit.uni-kl.de    delta_list(){
16312027Sjungma@eit.uni-kl.de      reset();
16412027Sjungma@eit.uni-kl.de      entries.resize(100);
16512027Sjungma@eit.uni-kl.de    }
16612027Sjungma@eit.uni-kl.de
16712027Sjungma@eit.uni-kl.de    inline void insert(const PAYLOAD& p){
16812027Sjungma@eit.uni-kl.de      if (size==entries.size()){
16912027Sjungma@eit.uni-kl.de        entries.resize(entries.size()*2);
17012027Sjungma@eit.uni-kl.de      }
17112027Sjungma@eit.uni-kl.de      entries[size++]=p;
17212027Sjungma@eit.uni-kl.de    }
17312027Sjungma@eit.uni-kl.de
17412027Sjungma@eit.uni-kl.de    inline PAYLOAD& get(){
17512027Sjungma@eit.uni-kl.de      return entries[out++];
17612027Sjungma@eit.uni-kl.de    }
17712027Sjungma@eit.uni-kl.de
17812027Sjungma@eit.uni-kl.de    inline bool next(){
17912027Sjungma@eit.uni-kl.de      return out<size;
18012027Sjungma@eit.uni-kl.de    }
18112027Sjungma@eit.uni-kl.de
18212027Sjungma@eit.uni-kl.de    inline void reset(){
18312027Sjungma@eit.uni-kl.de      size=0;
18412027Sjungma@eit.uni-kl.de      out=0;
18512027Sjungma@eit.uni-kl.de    }
18612027Sjungma@eit.uni-kl.de  public:
18712027Sjungma@eit.uni-kl.de    unsigned int size;
18812027Sjungma@eit.uni-kl.de  private:
18912027Sjungma@eit.uni-kl.de    std::vector<PAYLOAD> entries;
19012027Sjungma@eit.uni-kl.de    unsigned int out;
19112027Sjungma@eit.uni-kl.de  };
19212027Sjungma@eit.uni-kl.de
19312027Sjungma@eit.uni-kl.depublic:
19412027Sjungma@eit.uni-kl.de
19512027Sjungma@eit.uni-kl.de  peq_with_cb_and_phase(OWNER* _owner, cb _cb)
19612027Sjungma@eit.uni-kl.de    :sc_core::sc_object( sc_core::sc_gen_unique_name( "peq_with_cb_and_phase" ) )
19712027Sjungma@eit.uni-kl.de    ,m_owner(_owner)
19812027Sjungma@eit.uni-kl.de    ,m_cb(_cb)
19912027Sjungma@eit.uni-kl.de  {
20012027Sjungma@eit.uni-kl.de    sc_core::sc_spawn_options opts;
20112027Sjungma@eit.uni-kl.de    opts.spawn_method();
20212027Sjungma@eit.uni-kl.de    opts.set_sensitivity(&m_e);
20312027Sjungma@eit.uni-kl.de    opts.dont_initialize();
20412027Sjungma@eit.uni-kl.de    sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this),
20512027Sjungma@eit.uni-kl.de                      sc_core::sc_gen_unique_name("fec"), &opts);
20612027Sjungma@eit.uni-kl.de  }
20712027Sjungma@eit.uni-kl.de
20812027Sjungma@eit.uni-kl.de  peq_with_cb_and_phase(const char* _name, OWNER* _owner,cb _cb)
20912027Sjungma@eit.uni-kl.de    : sc_core::sc_object( _name )
21012027Sjungma@eit.uni-kl.de    ,m_owner(_owner)
21112027Sjungma@eit.uni-kl.de    ,m_cb(_cb)
21212027Sjungma@eit.uni-kl.de  {
21312027Sjungma@eit.uni-kl.de    sc_core::sc_spawn_options opts;
21412027Sjungma@eit.uni-kl.de    opts.spawn_method();
21512027Sjungma@eit.uni-kl.de    opts.set_sensitivity(&m_e);
21612027Sjungma@eit.uni-kl.de    opts.dont_initialize();
21712027Sjungma@eit.uni-kl.de    sc_core::sc_spawn(sc_bind(&peq_with_cb_and_phase::fec, this),
21812027Sjungma@eit.uni-kl.de                      sc_core::sc_gen_unique_name("fec"), &opts);
21912027Sjungma@eit.uni-kl.de  }
22012027Sjungma@eit.uni-kl.de
22112027Sjungma@eit.uni-kl.de  ~peq_with_cb_and_phase(){}
22212027Sjungma@eit.uni-kl.de
22312027Sjungma@eit.uni-kl.de  void notify (tlm_payload_type& t, const tlm_phase_type& p, const sc_core::sc_time& when){
22412027Sjungma@eit.uni-kl.de    //t.aquire();
22512027Sjungma@eit.uni-kl.de    if (when==sc_core::SC_ZERO_TIME) {
22612027Sjungma@eit.uni-kl.de      if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1) //uneven delta cycle so delta delay is for even cylce
22712027Sjungma@eit.uni-kl.de        m_even_delta.insert(PAYLOAD(&t,p));
22812027Sjungma@eit.uni-kl.de      else
22912027Sjungma@eit.uni-kl.de        m_uneven_delta.insert(PAYLOAD(&t,p)); //even delta cycle so delta delay is for uneven delta
23012027Sjungma@eit.uni-kl.de      m_e.notify(sc_core::SC_ZERO_TIME);
23112027Sjungma@eit.uni-kl.de    }
23212027Sjungma@eit.uni-kl.de    else {
23312027Sjungma@eit.uni-kl.de      m_ppq.insert(PAYLOAD(&t,p),  when + sc_core::sc_time_stamp() );
23412027Sjungma@eit.uni-kl.de      m_e.notify(when); // note, this will only over-right the "newest" event.
23512027Sjungma@eit.uni-kl.de    }
23612027Sjungma@eit.uni-kl.de  }
23712027Sjungma@eit.uni-kl.de
23812027Sjungma@eit.uni-kl.de  void notify (tlm_payload_type& t, const tlm_phase_type& p){
23912027Sjungma@eit.uni-kl.de    m_immediate_yield.insert(PAYLOAD(&t,p));
24012027Sjungma@eit.uni-kl.de    m_e.notify(); // immediate notification
24112027Sjungma@eit.uni-kl.de  }
24212027Sjungma@eit.uni-kl.de
24312027Sjungma@eit.uni-kl.de  // Cancel all events from the event queue
24412027Sjungma@eit.uni-kl.de  void cancel_all() {
24512027Sjungma@eit.uni-kl.de    m_ppq.reset();
24612027Sjungma@eit.uni-kl.de    m_uneven_delta.reset();
24712027Sjungma@eit.uni-kl.de    m_even_delta.reset();
24812027Sjungma@eit.uni-kl.de    m_immediate_yield.reset();
24912027Sjungma@eit.uni-kl.de    m_e.cancel();
25012027Sjungma@eit.uni-kl.de  }
25112027Sjungma@eit.uni-kl.de
25212027Sjungma@eit.uni-kl.deprivate:
25312027Sjungma@eit.uni-kl.de
25412027Sjungma@eit.uni-kl.de  void fec(){
25512027Sjungma@eit.uni-kl.de    //immediate yield notifications
25612027Sjungma@eit.uni-kl.de    while(m_immediate_yield.next()) {PAYLOAD& tmp=m_immediate_yield.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();}
25712027Sjungma@eit.uni-kl.de    m_immediate_yield.reset();
25812027Sjungma@eit.uni-kl.de
25912027Sjungma@eit.uni-kl.de    //delta notifications
26012027Sjungma@eit.uni-kl.de    if (sc_core::sc_delta_count() & (sc_dt::uint64) 0x1) {//uneven delta so put out all payloads for uneven delta
26112027Sjungma@eit.uni-kl.de      while (m_uneven_delta.next()) {PAYLOAD& tmp=m_uneven_delta.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();}
26212027Sjungma@eit.uni-kl.de      m_uneven_delta.reset();
26312027Sjungma@eit.uni-kl.de      if (m_even_delta.size) m_e.notify(sc_core::SC_ZERO_TIME);
26412027Sjungma@eit.uni-kl.de    }
26512027Sjungma@eit.uni-kl.de    else {
26612027Sjungma@eit.uni-kl.de      while (m_even_delta.next()) {PAYLOAD& tmp=m_even_delta.get(); (m_owner->*m_cb)(*tmp.first, tmp.second);} //tmp.first->release();}
26712027Sjungma@eit.uni-kl.de      m_even_delta.reset();
26812027Sjungma@eit.uni-kl.de      if (m_uneven_delta.size) m_e.notify(sc_core::SC_ZERO_TIME);
26912027Sjungma@eit.uni-kl.de    }
27012027Sjungma@eit.uni-kl.de    if (!m_ppq.get_size()) return; //there were only delta notification
27112027Sjungma@eit.uni-kl.de
27212027Sjungma@eit.uni-kl.de    //timed notifications
27312027Sjungma@eit.uni-kl.de    const sc_core::sc_time now=sc_core::sc_time_stamp();
27412027Sjungma@eit.uni-kl.de    sc_core::sc_time top=m_ppq.top_time();
27512027Sjungma@eit.uni-kl.de
27612027Sjungma@eit.uni-kl.de    while(m_ppq.get_size() && top==now) { // push all active ones into target
27712027Sjungma@eit.uni-kl.de      PAYLOAD& tmp=m_ppq.top();
27812027Sjungma@eit.uni-kl.de      (m_owner->*m_cb)(*tmp.first, tmp.second); //tmp.first->release();}
27912027Sjungma@eit.uni-kl.de      m_ppq.delete_top();
28012027Sjungma@eit.uni-kl.de      top=m_ppq.top_time();
28112027Sjungma@eit.uni-kl.de    }
28212027Sjungma@eit.uni-kl.de    if ( m_ppq.get_size()) {
28312027Sjungma@eit.uni-kl.de      m_e.notify( top - now) ;
28412027Sjungma@eit.uni-kl.de    }
28512027Sjungma@eit.uni-kl.de
28612027Sjungma@eit.uni-kl.de  }
28712027Sjungma@eit.uni-kl.de
28812027Sjungma@eit.uni-kl.de  OWNER* m_owner;
28912027Sjungma@eit.uni-kl.de  cb     m_cb;
29012027Sjungma@eit.uni-kl.de
29112027Sjungma@eit.uni-kl.de  time_ordered_list<PAYLOAD> m_ppq;
29212027Sjungma@eit.uni-kl.de  delta_list m_uneven_delta;
29312027Sjungma@eit.uni-kl.de  delta_list m_even_delta;
29412027Sjungma@eit.uni-kl.de  delta_list m_immediate_yield;
29512027Sjungma@eit.uni-kl.de
29612027Sjungma@eit.uni-kl.de  sc_core::sc_event m_e;   // default event
29712027Sjungma@eit.uni-kl.de};
29812027Sjungma@eit.uni-kl.de
29912027Sjungma@eit.uni-kl.de}
30012027Sjungma@eit.uni-kl.de
30112027Sjungma@eit.uni-kl.de#endif // __PEQ_WITH_CB_AND_PHASE_H__
302