quic/qbox
Loading...
Searching...
No Matches
sync_window.h
1/*
2 * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All Rights Reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <systemc>
8#include <tlm>
9#include <cci_configuration>
10#include <tlm_utils/tlm_quantumkeeper.h>
11#include <scp/report.h>
12#include <mutex>
13#include <type_traits>
14
15#ifdef SC_HAS_OB_EVENT
16#include <sysc/utils/sc_ob_event.h>
17#else
18#include "observer_event.h"
20#endif
21
22namespace sc_core {
23
30 virtual sc_core::sc_time quantum() = 0;
31 virtual bool keep_alive() = 0;
32};
34 sc_core::sc_time quantum() { return tlm_utils::tlm_quantumkeeper::get_global_quantum(); }
35 bool keep_alive() { return true; }
36};
38 sc_core::sc_time quantum()
39 {
40 return sc_core::sc_pending_activity() ? sc_core::sc_time_to_pending_activity() : sc_core::SC_ZERO_TIME;
41 }
42 bool keep_alive() { return false; }
43};
50template <class sc_sync_policy = sc_sync_policy_in_sync>
51class sc_sync_window : public sc_core::sc_module, public sc_core::sc_prim_channel
52{
53 static_assert(std::is_base_of<sc_sync_policy_base, sc_sync_policy>::value,
54 "sc_sync_policy must derive from sc_sync_policy_base");
55
56 sc_core::sc_event m_sweep_ev;
57 sc_ob_event m_step_ev;
58 sc_event m_update_ev;
59 std::mutex m_mutex;
60 sc_sync_policy policy;
61
62public:
63 struct window {
64 sc_core::sc_time from;
65 sc_core::sc_time to;
66 bool operator==(const window& other) const { return other.to == to && other.from == from; }
67 };
68
69 static inline const struct window zero_window = { sc_core::SC_ZERO_TIME, sc_core::SC_ZERO_TIME };
70 static inline const struct window open_window = { sc_core::SC_ZERO_TIME, sc_core::sc_max_time() };
71
72private:
73 window m_window;
74 window m_incomming_window; // used to hold the window values coming in from
75 // the other side.
76
77 std::function<void(const window&)> m_other_async_set_window_fn;
78
79 void do_other_async_set_window_fn(window w)
80 {
81 if (m_other_async_set_window_fn) {
82 auto now = sc_core::sc_time_stamp();
83 m_other_async_set_window_fn(w);
84 }
85 }
86
87 /* Handle suspending/resuming at the end of the window, also inform other side if we reach end of window */
88 void step_helper()
89 {
90 auto now = sc_core::sc_time_stamp();
91 auto to = m_window.to;
92 SCP_INFO(()) << "End window check"
93 << " their window " << m_window.from << " " << to;
94
95 if (now >= to) {
96 sc_core::sc_unsuspend_all(); // such that pending activity is valid if it's needed below.
97
98 /* We should suspend at this point, and wait for the other side to catch up */
99 SCP_TRACE(()) << "Suspend at: " << now << " quantum: " << policy.quantum();
100 do_other_async_set_window_fn({ now, now + policy.quantum() });
101
102 if (!policy.keep_alive()) async_attach_suspending();
103 sc_core::sc_suspend_all();
104
105 } else {
106 sc_core::sc_unsuspend_all();
107 if (!policy.keep_alive()) async_detach_suspending();
108
109 /* Re-notify event - maybe presumably moved */
110 m_step_ev.notify(to - now);
111 }
112 }
113
114 /*
115 * Handle all sweep requests, once we arrive at a sweep point, tell the other side.
116 */
117 void sweep_helper()
118 {
119 auto now = sc_core::sc_time_stamp();
120
121 SCP_INFO(()) << "Done sweep"
122 << " their window " << m_window.from << " - " << m_window.to;
123
124 do_other_async_set_window_fn({ now, now + policy.quantum() });
125 }
126
127 /* Manage the Sync aync update */
128 void update()
129 {
130 std::lock_guard<std::mutex> lg(m_mutex);
131 // Now we are on our thread, it's safe to update our window.
132 m_window = m_incomming_window;
133 auto now = sc_core::sc_time_stamp();
134 SCP_INFO(()) << "Update"
135 << " their window " << m_window.from << " - " << m_window.to;
136
137 if (m_window.from > now) {
138 m_sweep_ev.notify(m_window.from - now); // Try to move time forward.
139 } else {
140 m_sweep_ev.cancel(); // no need to fire event.
141 }
142 /* let stepper handle suspend/resume, must time notify */
143 m_update_ev.notify(sc_core::SC_ZERO_TIME);
144 }
145
146public:
147 SCP_LOGGER();
148
149 /* API call from other pair, presumably in a different thread.
150 * The internal window wil be updated atomically.
151 *
152 * Input: window - Window to set for sync. Sweep till the 'from' and step to the 'to'.
153 */
154 void async_set_window(const window& w)
155 {
156 /* Only accept updated windows so we dont re-send redundant updates */
157 std::lock_guard<std::mutex> lg(m_mutex);
158 m_incomming_window = w;
159 if (!(w == m_window)) {
160 SCP_INFO(()) << "sync " << w.from << " " << w.to;
162 }
163 }
164 void detach()
165 {
166 async_detach_suspending();
167 m_other_async_set_window_fn(open_window);
168 }
169 void bind(sc_sync_window* other)
170 {
171 if (m_other_async_set_window_fn) {
172 SC_REPORT_WARNING("sc_sync_window",
173 "m_other_async_set_window_fn was already registered or other "
174 "sc_sync_window was already bound!");
175 }
176 m_other_async_set_window_fn = std::bind(&sc_sync_window::async_set_window, other, std::placeholders::_1);
177 }
178 void register_sync_cb(std::function<void(const window&)> fn)
179 {
180 if (m_other_async_set_window_fn) {
181 SC_REPORT_WARNING("sc_sync_window",
182 "m_other_async_set_window_fn was already registered or other "
183 "sc_sync_window was already bound!");
184 }
185 m_other_async_set_window_fn = fn;
186 }
187 SC_CTOR (sc_sync_window) : m_window({sc_core::SC_ZERO_TIME, policy.quantum()})
188 {
189 SCP_TRACE(())("Constructor");
190 SC_METHOD(sweep_helper);
192 sensitive << m_sweep_ev;
193
194 SC_METHOD(step_helper);
196 sensitive << m_step_ev << m_update_ev;
197
198 m_step_ev.notify(sc_core::SC_ZERO_TIME);
199
200 this->sc_core::sc_prim_channel::async_attach_suspending();
201 }
202};
203
204} // namespace sc_core
Definition target.h:160
Definition observer_event.h:17
Definition keep_alive.h:20
windowed synchronizer, template SYNC_POLICY gives the quantum (dynamically) and specifies if the wind...
Definition sync_window.h:52
Base class which gives the quantum (dynamically) and specifies if the window should stay open indefin...
Definition sync_window.h:29
Definition sync_window.h:37
Definition sync_window.h:33
Definition sync_window.h:63