scc 2026.07
SystemC components library
quantum_keeper_mt.h
1#ifndef __SCC_TLM_QUANTUMKEEPER_MT_H__
2#define __SCC_TLM_QUANTUMKEEPER_MT_H__
3
4#include "qk/sc_time_syncronizer.h"
5#include <scc/async_thread.h>
6#include <sysc/kernel/sc_simcontext.h>
7
8#if SC_VERSION_MAJOR < 3
9#warning "Multithreaded quantum keeper is only supported with SystemC 3.0 and newer"
10#else
11#define DEBUG_MT_SCHEDULING
12
13namespace tlm {
14namespace scc {
18struct quantumkeeper_mt : sc_core::sc_object {
23 quantumkeeper_mt()
24 : sc_core::sc_object("qk")
25 , gtk_idx(qk::sc_time_syncronizer::get().get_channel_index()) {
26 sc_core::sc_spawn_options opt;
27 opt.spawn_method();
28 opt.set_sensitivity(&keep_alive);
29 }
34 virtual ~quantumkeeper_mt() = default;
35
36 void run_thread(std::function<sc_core::sc_time()> f) {
37 qk::sc_time_syncronizer::get().notify_client_blocked(gtk_idx, false);
38 reset(sc_core::sc_time_stamp());
39 thread_executor.start([this, f]() {
40 this->check_and_sync(sc_core::SC_ZERO_TIME);
41 auto ret = f();
42 qk::sc_time_syncronizer::get().notify_client_blocked(gtk_idx, true);
43 return ret;
44 });
45 wait(thread_executor.thread_finish_event());
46 }
52 inline void inc(sc_core::sc_time const& core_inc) {
53 local_absolute_time += core_inc;
54 local_time_ticks_limit = qk::global_time_keeper::get().get_client_max_time_ticks(gtk_idx);
55 }
61 inline void check_and_sync(sc_core::sc_time const& core_inc) {
62 inc(core_inc);
63 qk::global_time_keeper::get().update_client_time_ticks(gtk_idx, local_absolute_time.value());
64 // wait until the SystemC thread advanced to the same time then we are minus the global quantum
65 while(local_absolute_time.value() > local_time_ticks_limit) {
66 std::this_thread::yield(); // should do the same than __builtin_ia32_pause() or _mm_pause() on MSVC
67 local_time_ticks_limit = qk::global_time_keeper::get().get_client_max_time_ticks(gtk_idx);
68 }
69 }
75 inline void execute_on_sysc(std::function<void(void)> fct) { execute_on_sysc(fct, local_absolute_time); }
82 inline void execute_on_sysc(std::function<void(void)>& fct, sc_core::sc_time when) {
83 qk::callback_task task([this, &fct]() {
84 auto t0 = sc_core::sc_time_stamp();
85 fct();
86 return sc_core::sc_time_stamp() - t0;
87 });
88 auto ret = task.get_future();
89 qk::global_time_keeper::get().schedule_task(gtk_idx, std::move(task), when.value());
90 auto duration = ret.get();
91 check_and_sync(duration);
92 }
98 sc_core::sc_time get_local_time() const { return local_absolute_time - get_current_sc_time(); }
104 sc_core::sc_time get_local_absolute_time() const { return local_absolute_time; }
110 sc_core::sc_time get_current_sc_time() const { return sc_core::sc_time::from_value(qk::global_time_keeper::get().get_sc_time_ticks()); }
115 void reset() { reset(get_current_sc_time()); }
121 void reset(sc_core::sc_time const& abs_time) { local_absolute_time = sc_core::sc_time_stamp(); }
122
123 void unblock_thread() { qk::global_time_keeper::get().update_client_time_ticks(gtk_idx, local_absolute_time.value()); }
124
125protected:
126 size_t gtk_idx;
127 ::scc::async_thread thread_executor;
128 sc_core::sc_event keep_alive;
129 sc_core::sc_time local_absolute_time;
130 uint64_t local_time_ticks_limit{0};
131};
132} // namespace scc
133} // namespace tlm
134#endif
135#endif // __SCC_TLM_QUANTUMKEEPER_MT_H__
SCC TLM utilities.
Definition axis_tlm.h:56
SystemC TLM.
Definition dmi_mgr.h:19
uint64_t get_client_max_time_ticks(size_t idx)
Get the maximum time ticks a client thread is allowed to advance.
void update_client_time_ticks(size_t idx, uint64_t tick)
updates the global time keeper with the local time ticks of a clinet thread
static global_time_keeper & get()
the singleton getter
void schedule_task(size_t idx, std::packaged_task< sc_core::sc_time(void)> &&task, uint64_t when)
updates the global time keeper with the local time ticks of a clinet thread and schedules a task at t...
static sc_time_syncronizer & get()
the singleton getter
void execute_on_sysc(std::function< void(void)> fct)
execute the given function in the SystemC thread