1use core::cmp::Ordering;
8use std::cell::RefCell;
9use std::future::Future;
10use std::pin::Pin;
11use std::rc::Rc;
12use std::task::{Context, Poll, Waker};
13
14use crate::traits::{Resolve, Resolver};
15
16#[derive(Clone, Copy, Debug, PartialEq, Eq)]
18pub struct ClockTick {
19 tick: u64,
21
22 #[cfg(feature = "phase")]
23 phase: u32,
25}
26
27impl ClockTick {
28 #[must_use]
29 pub fn new() -> Self {
30 Self {
31 tick: 0,
32
33 #[cfg(feature = "phase")]
34 phase: 0,
35 }
36 }
37
38 #[must_use]
40 pub fn tick(&self) -> u64 {
41 self.tick
42 }
43
44 #[must_use]
46 #[cfg(feature = "phase")]
47 pub fn phase(&self) -> u32 {
48 self.phase
49 }
50
51 pub fn set_tick(&mut self, tick: u64) -> ClockTick {
53 self.tick = tick;
54 *self
55 }
56
57 #[cfg(feature = "phase")]
59 pub fn set_phase(&mut self, phase: u32) -> ClockTick {
60 self.phase = phase;
61 *self
62 }
63}
64
65impl Default for ClockTick {
66 fn default() -> Self {
67 Self::new()
68 }
69}
70
71impl Ord for ClockTick {
73 #[cfg(feature = "phase")]
74 fn cmp(&self, other: &Self) -> Ordering {
75 match self.tick.cmp(&other.tick) {
76 Ordering::Greater => Ordering::Greater,
77 Ordering::Less => Ordering::Less,
78 Ordering::Equal => self.phase.cmp(&other.phase),
79 }
80 }
81
82 #[cfg(not(feature = "phase"))]
83 fn cmp(&self, other: &Self) -> Ordering {
84 self.tick.cmp(&other.tick)
85 }
86}
87
88impl PartialOrd for ClockTick {
89 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
90 Some(self.cmp(other))
91 }
92}
93
94impl std::fmt::Display for ClockTick {
95 #[cfg(feature = "phase")]
96 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
97 write!(f, "{}.{:?}", self.tick, self.phase)
98 }
99 #[cfg(not(feature = "phase"))]
100 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
101 write!(f, "{}", self.tick)
102 }
103}
104
105#[derive(Clone)]
106pub struct Clock {
108 freq_mhz: f64,
111
112 pub shared_state: Rc<ClockState>,
113}
114
115pub struct TaskWaker {
116 pub waker: Waker,
118
119 pub can_exit: bool,
123}
124
125pub struct ClockState {
127 now: RefCell<ClockTick>,
128
129 pub waiting: RefCell<Vec<Vec<TaskWaker>>>,
131
132 pub waiting_times: RefCell<Vec<ClockTick>>,
135
136 pub to_resolve: RefCell<Vec<Rc<dyn Resolve + 'static>>>,
138}
139
140impl ClockState {
141 fn schedule(&self, schedule_time: ClockTick, cx: &mut Context<'_>, can_exit: bool) {
142 let mut waiting_times = self.waiting_times.borrow_mut();
143 let mut waiting = self.waiting.borrow_mut();
144 if let Some(index) = waiting_times.iter().position(|&x| x == schedule_time) {
145 waiting[index].push(TaskWaker {
147 waker: cx.waker().clone(),
148 can_exit,
149 });
150 } else {
151 match waiting_times.iter().position(|x| *x < schedule_time) {
153 Some(index) => {
154 waiting_times.insert(index, schedule_time);
156 waiting.insert(
157 index,
158 vec![TaskWaker {
159 waker: cx.waker().clone(),
160 can_exit,
161 }],
162 );
163 }
164 None => {
165 waiting_times.push(schedule_time);
167 waiting.push(vec![TaskWaker {
168 waker: cx.waker().clone(),
169 can_exit,
170 }]);
171 }
172 }
173 }
174 }
175
176 fn advance_time(&self, to_time: ClockTick) {
177 self.resolve();
178 if to_time != *self.now.borrow() {
179 assert!(to_time >= *self.now.borrow(), "Time moving backwards");
180 *self.now.borrow_mut() = to_time;
181 }
182 }
183
184 fn resolve(&self) {
185 for r in self.to_resolve.borrow_mut().drain(..) {
186 r.resolve();
187 }
188 }
189}
190
191impl Clock {
192 #[must_use]
194 pub fn new(freq_mhz: f64) -> Self {
195 let shared_state = Rc::new(ClockState {
196 now: RefCell::new(ClockTick {
197 tick: 0,
198 #[cfg(feature = "phase")]
199 phase: 0,
200 }),
201 waiting: RefCell::new(Vec::new()),
202 waiting_times: RefCell::new(Vec::new()),
203 to_resolve: RefCell::new(Vec::new()),
204 });
205
206 Self {
207 freq_mhz,
208 shared_state,
209 }
210 }
211
212 #[must_use]
214 pub fn freq_mhz(&self) -> f64 {
215 self.freq_mhz
216 }
217
218 #[must_use]
220 pub fn tick_now(&self) -> ClockTick {
221 *self.shared_state.now.borrow()
222 }
223
224 #[must_use]
226 pub fn time_now_ns(&self) -> f64 {
227 let now = *self.shared_state.now.borrow();
228 self.to_ns(&now)
229 }
230
231 #[must_use]
233 pub fn time_of_next(&self) -> f64 {
234 match self.shared_state.waiting_times.borrow().first() {
235 Some(clock_time) => self.to_ns(clock_time),
236 None => f64::MAX,
237 }
238 }
239
240 #[must_use]
242 pub fn to_ns(&self, clock_time: &ClockTick) -> f64 {
243 clock_time.tick as f64 / self.freq_mhz * 1000.0
244 }
245
246 #[must_use = "Futures do nothing unless you `.await` or otherwise use them"]
249 pub fn wait_ticks(&self, ticks: u64) -> ClockDelay {
250 let mut until = self.tick_now();
251 until.tick += ticks;
252 ClockDelay {
253 shared_state: self.shared_state.clone(),
254 until,
255 state: ClockDelayState::Pending,
256 can_exit: false,
257 }
258 }
259
260 #[must_use = "Futures do nothing unless you `.await` or otherwise use them"]
266 pub fn wait_ticks_or_exit(&self, ticks: u64) -> ClockDelay {
267 let mut until = self.tick_now();
268 until.tick += ticks;
269 ClockDelay {
270 shared_state: self.shared_state.clone(),
271 until,
272 state: ClockDelayState::Pending,
273 can_exit: true,
274 }
275 }
276
277 #[must_use = "Futures do nothing unless you `.await` or otherwise use them"]
278 #[cfg(feature = "phase")]
279 pub fn next_tick_and_phase(&self, phase: u32) -> ClockDelay {
280 let mut until = self.tick_now();
281 until.tick += 1;
282 until.phase = phase;
283 ClockDelay {
284 shared_state: self.shared_state.clone(),
285 until,
286 state: ClockDelayState::Pending,
287 can_exit: false,
288 }
289 }
290
291 #[must_use = "Futures do nothing unless you `.await` or otherwise use them"]
292 #[cfg(feature = "phase")]
293 pub fn wait_phase(&self, phase: u32) -> ClockDelay {
294 let mut until = self.tick_now();
295 assert!(phase > until.phase, "Time going backwards");
296 until.phase = phase;
297 ClockDelay {
298 shared_state: self.shared_state.clone(),
299 until,
300 state: ClockDelayState::Pending,
301 can_exit: false,
302 }
303 }
304
305 pub fn advance_to(&self, time_ns: f64) {
307 let now_ns = self.time_now_ns();
308 assert!(now_ns < time_ns);
309 let diff_ns = time_ns - now_ns;
310 let ticks = (diff_ns * (self.freq_mhz / 1000.0)).ceil();
311
312 let mut until = self.tick_now();
313 until.tick += ticks as u64;
314
315 self.shared_state.advance_time(until);
316 }
317}
318
319impl Default for Clock {
321 fn default() -> Self {
322 Self::new(1000.0)
323 }
324}
325
326impl PartialEq for Clock {
328 fn eq(&self, other: &Self) -> bool {
329 self.time_of_next() == other.time_of_next()
330 }
331}
332impl Eq for Clock {}
333
334impl Ord for Clock {
335 fn cmp(&self, other: &Self) -> Ordering {
336 if self.time_of_next() < other.time_of_next() {
337 Ordering::Less
338 } else {
339 Ordering::Greater
340 }
341 }
342}
343
344impl PartialOrd for Clock {
345 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
346 Some(self.cmp(other))
347 }
348}
349
350impl Resolver for Clock {
351 fn add_resolve(&self, resolve: Rc<dyn Resolve + 'static>) {
352 self.shared_state.to_resolve.borrow_mut().push(resolve);
353 }
354}
355
356enum ClockDelayState {
358 Pending,
359 Running,
360}
361
362pub struct ClockDelay {
364 shared_state: Rc<ClockState>,
365 until: ClockTick,
366 state: ClockDelayState,
367 can_exit: bool,
368}
369
370impl Future for ClockDelay {
371 type Output = ();
372 fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
373 match self.state {
374 ClockDelayState::Pending => {
375 self.shared_state.schedule(self.until, cx, self.can_exit);
376 self.state = ClockDelayState::Running;
377 Poll::Pending
378 }
379 ClockDelayState::Running => {
380 self.shared_state.advance_time(self.until);
381 Poll::Ready(())
382 }
383 }
384 }
385}
386
387#[cfg(test)]
388mod tests {
389 use super::*;
390
391 #[test]
392 fn convert_to_ns() {
393 let clk_ghz = Clock::new(1000.0);
394 assert_eq!(1.0, clk_ghz.to_ns(&ClockTick::new().set_tick(1)));
395
396 let slow_clk = Clock::new(0.5);
397 assert_eq!(2000.0, slow_clk.to_ns(&ClockTick::new().set_tick(1)));
398 }
399}