gem5  v19.0.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 
56  time_ordered_list() : nill(new element()), empties(NULL),
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;
91  e->d = sc_core::sc_delta_count();
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; }
123  sc_core::sc_time top_time() { return list->t; }
124  sc_dt::uint64 &top_delta() { return list->d; }
125  sc_core::sc_time next_time() { return list->next->t; }
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) :
179  sc_core::sc_object(sc_core::sc_gen_unique_name(
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
205  notify(tlm_payload_type &t, const tlm_phase_type &p,
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.
211  m_even_delta.insert(PAYLOAD(&t,p));
212  } else {
213  // Even delta cycle so delta delay is for uneven delta.
214  m_uneven_delta.insert(PAYLOAD(&t, p));
215  }
216  m_e.notify(sc_core::SC_ZERO_TIME);
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
225  notify(tlm_payload_type &t, const tlm_phase_type &p)
226  {
227  m_immediate_yield.insert(PAYLOAD(&t, p));
228  m_e.notify(); // Immediate notification.
229  }
230 
231  // Cancel all events from the event queue.
232  void
234  {
235  m_ppq.reset();
236  m_uneven_delta.reset();
237  m_even_delta.reset();
238  m_immediate_yield.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  }
251  m_immediate_yield.reset();
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  }
260  m_uneven_delta.reset();
261  if (m_even_delta.size)
262  m_e.notify(sc_core::SC_ZERO_TIME);
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  }
268  m_even_delta.reset();
269  if (m_uneven_delta.size)
270  m_e.notify(sc_core::SC_ZERO_TIME);
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;
292  cb m_cb;
293 
295  delta_list m_uneven_delta;
296  delta_list m_even_delta;
297  delta_list m_immediate_yield;
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__ */
element(PAYLOAD &p, sc_core::sc_time t, sc_dt::uint64 d)
std::pair< tlm_payload_type *, tlm_phase_type > PAYLOAD
Definition: test.h:61
TYPES::tlm_payload_type tlm_payload_type
void insert(const PAYLOAD &p, sc_core::sc_time t)
STL pair class.
Definition: stl.hh:61
const char * sc_gen_unique_name(const char *seed)
Definition: sc_module.cc:822
void notify(tlm_payload_type &t, const tlm_phase_type &p, const sc_core::sc_time &when)
sc_process_handle sc_spawn(T object, const char *name_p=nullptr, const sc_spawn_options *opt_p=nullptr)
Definition: sc_spawn.hh:156
time_ordered_list< PAYLOAD > m_ppq
STL vector class.
Definition: stl.hh:40
peq_with_cb_and_phase(OWNER *_owner, cb _cb)
peq_with_cb_and_phase(const char *_name, OWNER *_owner, cb _cb)
An event queue that can contain any number of pending notifications.
void set_sensitivity(const sc_event *)
Definition: sc_spawn.cc:148
const sc_time & sc_time_stamp()
Definition: sc_main.cc:130
Bitfield< 9 > e
const sc_time SC_ZERO_TIME
Definition: sc_time.cc:292
uint64_t uint64
Definition: sc_nbdefs.hh:172
auto sc_bind(F &&f, Args &&...args) -> decltype(std::bind(std::forward< F >(f), std::forward< Args >(args)...))
Definition: sc_spawn.hh:200
void notify(tlm_payload_type &t, const tlm_phase_type &p)
top(sc_module_name)
Definition: test.h:74
sc_dt::uint64 sc_delta_count()
Definition: sc_main.cc:138

Generated on Fri Feb 28 2020 16:27:04 for gem5 by doxygen 1.8.13