1#include "global_time_keeper.h"
3#include <tlm_utils/tlm_quantumkeeper.h>
11global_time_keeper::global_time_keeper() =
default;
13global_time_keeper::~global_time_keeper() {
19void global_time_keeper::start() {
20 std::thread t{&global_time_keeper::sync_local_times,
this};
25size_t global_time_keeper::get_channel_index() {
27 throw std::runtime_error(
"global_time_keeper already started");
28 client_coms_channels.emplace_back(client_coms_channels.size());
30 return client_coms_channels.size() - 1;
34void global_time_keeper::sync_local_times() {
35 std::unique_lock<std::mutex> lock{upd_mtx};
37 update.wait_for(lock, std::chrono::milliseconds(1),
38 [
this]() ->
bool {
return update_it.load(std::memory_order_relaxed) || stop_it.load(std::memory_order_relaxed); });
39 if(update_it.exchange(
false)) {
40#ifdef DEBUG_MT_SCHEDULING
41 SCCTRACEALL(
"global_time_keeper::sync_local_times") <<
"update loop";
43 while(
auto res = sc_coms_channel.client2time_keeper.front()) {
44 sc_coms_channel.thread_local_time = res->time_tick;
45 sc_coms_channel.client2time_keeper.pop();
47 uint64_t min_local_time = std::numeric_limits<uint64_t>::max();
48 for(
size_t i = 0; i < client_coms_channels.size(); ++i) {
49 auto& client_coms_channel = client_coms_channels[i];
50 bool has_task =
false;
51 bool has_entries =
false;
52 while(
auto res = client_coms_channel.client2time_keeper.front()) {
54 client_coms_channel.thread_local_time = res->time_tick;
55 if(res->task.valid()) {
56#ifdef DEBUG_MT_SCHEDULING
57 SCCTRACEALL(
"global_time_keeper::sync_local_times")
58 <<
"forwarding task of client " << client_coms_channel.my_id <<
" with timestamp t=" << res->time_tick;
60 pending_tasks.emplace(client_coms_channel.my_id, res->time_tick, std::move(res->task));
63 client_coms_channel.client2time_keeper.pop();
66 client_coms_channel.waiting4sc = has_task;
67 if(!client_coms_channel.waiting4sc)
68 min_local_time = std::min(client_coms_channel.thread_local_time, min_local_time);
69#ifdef DEBUG_MT_SCHEDULING
71 SCCTRACEALL(
"global_time_keeper::sync_local_times")
72 <<
"thread_local_time[" << i <<
"]=" << sc_core::sc_time::from_value(client_coms_channel.thread_local_time)
73 << (client_coms_channel.waiting4sc ?
" (waiting)" :
" (running)");
78 if(min_local_time == std::numeric_limits<uint64_t>::max())
79 min_local_time = sc_coms_channel.thread_local_time;
80 client_min_time = min_local_time;
82 client_max_time = min_local_time + std::max(tlm::tlm_global_quantum::instance().
get().value(),
sc_time_step.value());
83 sc_kernel_time = sc_coms_channel.thread_local_time;
84#ifdef DEBUG_MT_SCHEDULING
85 SCCTRACEALL(
"global_time_keeper::sync_local_times") <<
"window_min_time=" << client_min_time;
87 }
else if(stop_it.load()) {
static global_time_keeper & get()
the singleton getter
const sc_core::sc_time sc_time_step
the maximum timestep the simulator is allowed to do if there are no future events