gem5  v22.1.0.0
peq_with_cb_and_phase.h
Go to the documentation of this file.
1 /*****************************************************************************
2 
3  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4  more contributor license agreements. See the NOTICE file distributed
5  with this work for additional information regarding copyright ownership.
6  Accellera licenses this file to you under the Apache License, Version 2.0
7  (the "License"); you may not use this file except in compliance with the
8  License. You may obtain a copy of the License at
9 
10  http://www.apache.org/licenses/LICENSE-2.0
11 
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15  implied. See the License for the specific language governing
16  permissions and limitations under the License.
17 
18  *****************************************************************************/
19 
20 #ifndef __SYSTEMC_EXT_TLM_UTILS_PEQ_WITH_CB_AND_PHASE_H__
21 #define __SYSTEMC_EXT_TLM_UTILS_PEQ_WITH_CB_AND_PHASE_H__
22 
23 #include <vector>
24 
25 #include "../core/sc_main.hh"
26 #include "../core/sc_object.hh"
27 #include "../core/sc_spawn.hh"
28 #include "../core/sc_time.hh"
29 #include "../dt/int/sc_nbdefs.hh"
30 #include "../tlm_core/2/interfaces/fw_bw_ifs.hh"
31 
32 namespace tlm_utils
33 {
34 
35 template <typename PAYLOAD>
37 {
38  public:
39  struct element
40  {
41  struct element *next;
42  PAYLOAD p;
46  p(p), t(t), d(d)
47  {}
48  element() {}
49  };
50 
54  unsigned int size;
55 
57  list(nill), size(0)
58  {}
59 
61  {
62  reset();
63  while (empties) {
64  struct element *e = empties->next;
65  delete empties;
66  empties = e;
67  }
68  delete nill;
69  }
70 
71  void
73  {
74  while (size) {
75  delete_top();
76  }
77  }
78 
79  void
80  insert(const PAYLOAD &p, sc_core::sc_time t)
81  {
82  if (!empties) {
83  empties = new struct element();
84  empties->next=NULL;
85  }
86 
87  struct element *e = empties;
88  empties = empties->next;
89  e->p = p;
90  e->t = t;
92 
93  struct element *ancestor = nill;
94  struct element *iterator = list;
95  while (iterator != nill && iterator->t <= t) {
96  ancestor = iterator;
97  iterator = iterator->next;
98  }
99  if (ancestor == nill) {
100  e->next = list;
101  list = e;
102  } else {
103  e->next = iterator;
104  ancestor->next = e;
105  }
106  size++;
107  }
108 
109  void
111  {
112  if (list != nill) {
113  struct element *e = list;
114  list = list->next;
115  e->next = empties;
116  empties = e;
117  size--;
118  }
119  }
120 
121  unsigned int get_size() { return size; }
122  PAYLOAD &top() { return list->p; }
124  sc_dt::uint64 &top_delta() { return list->d; }
126 };
127 
128 //---------------------------------------------------------------------------
133 //---------------------------------------------------------------------------
134 template<typename OWNER, typename TYPES=tlm::tlm_base_protocol_types>
136 {
137  typedef typename TYPES::tlm_payload_type tlm_payload_type;
138  typedef typename TYPES::tlm_phase_type tlm_phase_type;
140  typedef void (OWNER::*cb)(tlm_payload_type &, const tlm_phase_type &);
141 
143  {
144  public:
146  {
147  reset();
148  entries.resize(100);
149  }
150 
151  inline void
152  insert(const PAYLOAD &p)
153  {
154  if (size==entries.size()) {
155  entries.resize(entries.size() * 2);
156  }
157  entries[size++] = p;
158  }
159 
160  inline PAYLOAD &get() { return entries[out++]; }
161  inline bool next() { return out < size; }
162  inline void
164  {
165  size=0;
166  out=0;
167  }
168 
169  public:
170  unsigned int size;
171 
172  private:
174  unsigned int out;
175  };
176 
177  public:
178  peq_with_cb_and_phase(OWNER *_owner, cb _cb) :
180  "peq_with_cb_and_phase")),
181  m_owner(_owner), m_cb(_cb)
182  {
184  opts.spawn_method();
185  opts.set_sensitivity(&m_e);
186  opts.dont_initialize();
188  sc_core::sc_gen_unique_name("fec"), &opts);
189  }
190 
191  peq_with_cb_and_phase(const char *_name, OWNER *_owner, cb _cb) :
192  sc_core::sc_object(_name), m_owner(_owner), m_cb(_cb)
193  {
195  opts.spawn_method();
196  opts.set_sensitivity(&m_e);
197  opts.dont_initialize();
199  sc_core::sc_gen_unique_name("fec"), &opts);
200  }
201 
203 
204  void
206  const sc_core::sc_time &when)
207  {
208  if (when == sc_core::SC_ZERO_TIME) {
209  if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1) {
210  // Uneven delta cycle so delta delay is for even cycle.
212  } else {
213  // Even delta cycle so delta delay is for uneven delta.
215  }
217  } else {
218  m_ppq.insert(PAYLOAD(&t, p), when + sc_core::sc_time_stamp());
219  // Note, this will only overwrite the "newest" event.
220  m_e.notify(when);
221  }
222  }
223 
224  void
226  {
228  m_e.notify(); // Immediate notification.
229  }
230 
231  // Cancel all events from the event queue.
232  void
234  {
235  m_ppq.reset();
239  m_e.cancel();
240  }
241 
242  private:
243  void
244  fec()
245  {
246  // Immediate yield notifications.
247  while (m_immediate_yield.next()) {
248  PAYLOAD &tmp = m_immediate_yield.get();
249  (m_owner->*m_cb)(*tmp.first, tmp.second);
250  }
252 
253  // Delta notifications.
254  if (sc_core::sc_delta_count() & (sc_dt::uint64)0x1) {
255  // Uneven delta so put out all payloads for uneven delta.
256  while (m_uneven_delta.next()) {
257  PAYLOAD &tmp = m_uneven_delta.get();
258  (m_owner->*m_cb)(*tmp.first, tmp.second);
259  }
261  if (m_even_delta.size)
263  } else {
264  while (m_even_delta.next()) {
265  PAYLOAD &tmp = m_even_delta.get();
266  (m_owner->*m_cb)(*tmp.first, tmp.second);
267  }
269  if (m_uneven_delta.size)
271  }
272  if (!m_ppq.get_size())
273  return; // There were only delta notification.
274 
275  // Timed notifications.
277  sc_core::sc_time top = m_ppq.top_time();
278 
279  while (m_ppq.get_size() && top == now) {
280  // Push all active ones into target.
281  PAYLOAD &tmp = m_ppq.top();
282  (m_owner->*m_cb)(*tmp.first, tmp.second);
283  m_ppq.delete_top();
284  top = m_ppq.top_time();
285  }
286  if (m_ppq.get_size()) {
287  m_e.notify(top - now);
288  }
289  }
290 
291  OWNER *m_owner;
293 
298 
299  sc_core::sc_event m_e; // Default event.
300 };
301 
302 } // namespace tlm_utils
303 
304 #endif /* __SYSTEMC_EXT_TLM_UTILS_PEQ_WITH_CB_AND_PHASE_H__ */
void set_sensitivity(const sc_event *)
Definition: sc_spawn.cc:146
STL pair class.
Definition: stl.hh:58
STL vector class.
Definition: stl.hh:37
An event queue that can contain any number of pending notifications.
peq_with_cb_and_phase(OWNER *_owner, cb _cb)
std::pair< tlm_payload_type *, tlm_phase_type > PAYLOAD
peq_with_cb_and_phase(const char *_name, OWNER *_owner, cb _cb)
time_ordered_list< PAYLOAD > m_ppq
TYPES::tlm_payload_type tlm_payload_type
void(OWNER::* cb)(tlm_payload_type &, const tlm_phase_type &)
void notify(tlm_payload_type &t, const tlm_phase_type &p)
void notify(tlm_payload_type &t, const tlm_phase_type &p, const sc_core::sc_time &when)
void insert(const PAYLOAD &p, sc_core::sc_time t)
Definition: test.h:63
Bitfield< 9 > e
Definition: misc_types.hh:65
Bitfield< 51 > t
Definition: pagetable.hh:56
Bitfield< 54 > p
Definition: pagetable.hh:70
sc_dt::uint64 sc_delta_count()
Definition: sc_main.cc:135
const sc_time SC_ZERO_TIME
Definition: sc_time.cc:290
sc_process_handle sc_spawn(T object, const char *name_p=nullptr, const sc_spawn_options *opt_p=nullptr)
Definition: sc_spawn.hh:154
auto sc_bind(F &&f, Args &&...args) -> decltype(std::bind(std::forward< F >(f), std::forward< Args >(args)...))
Definition: sc_spawn.hh:198
const char * sc_gen_unique_name(const char *seed)
Definition: sc_module.cc:820
const sc_time & sc_time_stamp()
Definition: sc_main.cc:127
uint64_t uint64
Definition: sc_nbdefs.hh:172
element(PAYLOAD &p, sc_core::sc_time t, sc_dt::uint64 d)

Generated on Wed Dec 21 2022 10:22:42 for gem5 by doxygen 1.9.1