scc 2025.09
SystemC components library
peq.h
1/*******************************************************************************
2 * Copyright 2018 MINRES Technologies GmbH
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *******************************************************************************/
16
17#ifndef _SCC_PEQ_H_
18#define _SCC_PEQ_H_
19
20#include <boost/optional.hpp>
21#include <deque>
22#include <map>
23#include <systemc>
24#include <type_traits>
25#include <vector>
26
32namespace scc {
41template <class TYPE> struct peq : public sc_core::sc_object {
42
43 // static_assert(std::is_copy_constructible<TYPE>::value, "TYPE needs to be copy-constructible");
44
45 using pair_type = std::pair<const sc_core::sc_time, TYPE>;
46 using map_type = std::map<const sc_core::sc_time, std::deque<TYPE>*>;
53 : sc_core::sc_object(sc_core::sc_gen_unique_name("peq")) {}
54
60 explicit peq(const char* name)
61 : sc_core::sc_object(name) {}
62
77 void notify(TYPE const& entry, const sc_core::sc_time& t) {
78 insert_entry(entry, t + sc_core::sc_time_stamp());
79 m_event.notify(m_scheduled_events.begin()->first - sc_core::sc_time_stamp());
80 }
81
90 void notify(TYPE&& entry, const sc_core::sc_time& t) {
91 insert_entry(std::move(entry), t + sc_core::sc_time_stamp());
92 m_event.notify(m_scheduled_events.begin()->first - sc_core::sc_time_stamp());
93 }
102 void notify(TYPE&& entry) {
103 insert_entry(std::move(entry), sc_core::sc_time_stamp());
104 m_event.notify(); // immediate notification
105 }
114 void notify(TYPE const& entry) {
115 insert_entry(entry, sc_core::sc_time_stamp());
116 m_event.notify(); // immediate notification
117 }
118
124 boost::optional<TYPE> get_next() {
125 if(m_scheduled_events.empty())
126 return boost::none;
127 sc_core::sc_time now = sc_core::sc_time_stamp();
128 if(!m_scheduled_events.size() || m_scheduled_events.begin()->first > now) {
129 if(m_scheduled_events.size())
130 m_event.notify(m_scheduled_events.begin()->first - now);
131 return boost::none;
132 } else
133 return get_entry();
134 }
135
141 TYPE get() {
142 while(!has_next()) {
143 sc_core::wait(event());
144 }
145 return get_entry();
146 }
147
153 sc_core::sc_event& event() { return m_event; }
159 void cancel_all() {
160 m_scheduled_events.clear();
161 m_event.cancel();
162 }
163
169 bool has_next() { return !(m_scheduled_events.empty() || m_scheduled_events.begin()->first > sc_core::sc_time_stamp()); }
170
171 void clear() {
172 while(!m_scheduled_events.empty()) {
173 auto queue = m_scheduled_events.begin()->second;
174 queue->clear();
175 free_pool.push_back(queue);
176 m_scheduled_events.erase(m_scheduled_events.begin());
177 }
178 }
179
180 size_t size() const { return m_scheduled_events.size(); }
181
182private:
183 map_type m_scheduled_events;
184 std::deque<std::deque<TYPE>*> free_pool;
185 sc_core::sc_event m_event;
186
187 void insert_entry(const TYPE& entry, sc_core::sc_time abs_time) {
188 auto it = m_scheduled_events.find(abs_time);
189 if(it == m_scheduled_events.end()) {
190 if(free_pool.size()) {
191 auto r = m_scheduled_events.insert(std::make_pair(abs_time, free_pool.front()));
192 free_pool.pop_front();
193 r.first->second->push_back(entry);
194 } else {
195 auto r = m_scheduled_events.insert(std::make_pair(abs_time, new std::deque<TYPE>()));
196 r.first->second->push_back(entry);
197 }
198 } else
199 it->second->push_back(entry);
200 }
201
202 void insert_entry(TYPE&& entry, sc_core::sc_time abs_time) {
203 auto it = m_scheduled_events.find(abs_time);
204 if(it == m_scheduled_events.end()) {
205 if(free_pool.size()) {
206 auto r = m_scheduled_events.insert(std::make_pair(abs_time, free_pool.front()));
207 free_pool.pop_front();
208 r.first->second->push_back(std::move(entry));
209 } else {
210 auto r = m_scheduled_events.insert(std::make_pair(abs_time, new std::deque<TYPE>()));
211 r.first->second->push_back(std::move(entry));
212 }
213 } else
214 it->second->push_back(std::move(entry));
215 }
216
217 TYPE get_entry() {
218 auto entry = m_scheduled_events.begin()->second;
219 auto ret = std::move(entry->front());
220 entry->pop_front();
221 if(!entry->size()) {
222 free_pool.push_back(entry);
223 m_scheduled_events.erase(m_scheduled_events.begin());
224 }
225 if(m_scheduled_events.size())
226 m_event.notify(m_scheduled_events.begin()->first - sc_core::sc_time_stamp());
227 return ret;
228 }
229};
230
231template <class TYPE> inline peq<TYPE>::~peq() {
232 while(m_scheduled_events.size()) {
233 free_pool.push_back(m_scheduled_events.begin()->second);
234 m_scheduled_events.erase(m_scheduled_events.begin());
235 }
236 for(auto* p : free_pool)
237 delete p;
238}
239
240} // namespace scc // end of scc-sysc
242#endif /* _SCC_PEQ_H_ */
SCC TLM utilities.
peq()
default constructor creating a unnamed peq
Definition peq.h:52
void notify(TYPE const &entry)
non-blocking push
Definition peq.h:114
bool has_next()
check if value is available at current time
Definition peq.h:169
~peq()
destructor
Definition peq.h:231
TYPE get()
blocking get
Definition peq.h:141
void cancel_all()
cancel all events from the event queue
Definition peq.h:159
boost::optional< TYPE > get_next()
non-blocking get
Definition peq.h:124
void notify(TYPE const &entry, const sc_core::sc_time &t)
non-blocking push.
Definition peq.h:77
peq(const char *name)
named peq constructor
Definition peq.h:60
sc_core::sc_event & event()
get the available event
Definition peq.h:153