Skip to main content

celox_runtime/
scheduler.rs

1use crate::{
2    SignalRef,
3    backend::{EventHandle, SimBackend},
4};
5use std::collections::BinaryHeap;
6
7#[derive(Debug, Clone)]
8pub struct ClockDef {
9    pub period: u64,
10}
11
12#[derive(Debug)]
13pub struct SimEvent<B: SimBackend> {
14    pub time: u64,
15    pub event_ref: B::Event,
16    pub signal: SignalRef,
17    pub next_val: u8,
18}
19
20// Manual impl: a derive would require `B: Clone`, which no backend is.
21impl<B: SimBackend> Clone for SimEvent<B> {
22    fn clone(&self) -> Self {
23        Self {
24            time: self.time,
25            event_ref: self.event_ref,
26            signal: self.signal,
27            next_val: self.next_val,
28        }
29    }
30}
31
32impl<B: SimBackend> PartialEq for SimEvent<B> {
33    fn eq(&self, other: &Self) -> bool {
34        self.time == other.time
35            && self.event_ref.addr() == other.event_ref.addr()
36            && self.signal == other.signal
37            && self.next_val == other.next_val
38    }
39}
40
41impl<B: SimBackend> Eq for SimEvent<B> {}
42
43impl<B: SimBackend> PartialOrd for SimEvent<B> {
44    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
45        Some(self.cmp(other))
46    }
47}
48
49impl<B: SimBackend> Ord for SimEvent<B> {
50    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
51        // Earlier time has higher priority (BinaryHeap is a Max-Heap)
52        other
53            .time
54            .cmp(&self.time)
55            .then_with(|| {
56                let id1 = self.event_ref.id();
57                let id2 = other.event_ref.id();
58                id2.cmp(&id1)
59            })
60            .then_with(|| other.signal.cmp(&self.signal))
61            .then_with(|| other.next_val.cmp(&self.next_val))
62    }
63}
64
65pub struct Scheduler<B: SimBackend> {
66    pub time: u64,
67    pub clocks: Vec<Option<ClockDef>>,
68    pub event_queue: BinaryHeap<SimEvent<B>>,
69}
70
71impl<B: SimBackend> Scheduler<B> {
72    pub fn new() -> Self {
73        Self {
74            time: 0,
75            clocks: Vec::new(),
76            event_queue: BinaryHeap::new(),
77        }
78    }
79
80    pub fn next_event_time(&self) -> Option<u64> {
81        self.event_queue.peek().map(|e| e.time)
82    }
83
84    pub fn push(&mut self, event: SimEvent<B>) {
85        self.event_queue.push(event);
86    }
87
88    pub fn pop_all_at_next_time(&mut self) -> Option<(u64, Vec<SimEvent<B>>)> {
89        let next_time = self.next_event_time()?;
90        let mut events = Vec::new();
91        while let Some(ev) = self.event_queue.peek() {
92            if ev.time == next_time {
93                events.push(self.event_queue.pop().unwrap());
94            } else {
95                break;
96            }
97        }
98        Some((next_time, events))
99    }
100}
101
102impl<B: SimBackend> Default for Scheduler<B> {
103    fn default() -> Self {
104        Self::new()
105    }
106}