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, Clone)]
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
20impl<B: SimBackend> PartialEq for SimEvent<B> {
21    fn eq(&self, other: &Self) -> bool {
22        self.time == other.time
23            && self.event_ref.addr() == other.event_ref.addr()
24            && self.signal == other.signal
25            && self.next_val == other.next_val
26    }
27}
28
29impl<B: SimBackend> Eq for SimEvent<B> {}
30
31impl<B: SimBackend> PartialOrd for SimEvent<B> {
32    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
33        Some(self.cmp(other))
34    }
35}
36
37impl<B: SimBackend> Ord for SimEvent<B> {
38    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
39        // Earlier time has higher priority (BinaryHeap is a Max-Heap)
40        other
41            .time
42            .cmp(&self.time)
43            .then_with(|| {
44                let id1 = self.event_ref.id();
45                let id2 = other.event_ref.id();
46                id2.cmp(&id1)
47            })
48            .then_with(|| other.signal.cmp(&self.signal))
49            .then_with(|| other.next_val.cmp(&self.next_val))
50    }
51}
52
53pub struct Scheduler<B: SimBackend> {
54    pub time: u64,
55    pub clocks: Vec<Option<ClockDef>>,
56    pub event_queue: BinaryHeap<SimEvent<B>>,
57}
58
59impl<B: SimBackend> Scheduler<B> {
60    pub fn new() -> Self {
61        Self {
62            time: 0,
63            clocks: Vec::new(),
64            event_queue: BinaryHeap::new(),
65        }
66    }
67
68    pub fn next_event_time(&self) -> Option<u64> {
69        self.event_queue.peek().map(|e| e.time)
70    }
71
72    pub fn push(&mut self, event: SimEvent<B>) {
73        self.event_queue.push(event);
74    }
75
76    pub fn pop_all_at_next_time(&mut self) -> Option<(u64, Vec<SimEvent<B>>)> {
77        let next_time = self.next_event_time()?;
78        let mut events = Vec::new();
79        while let Some(ev) = self.event_queue.peek() {
80            if ev.time == next_time {
81                events.push(self.event_queue.pop().unwrap());
82            } else {
83                break;
84            }
85        }
86        Some((next_time, events))
87    }
88}
89
90impl<B: SimBackend> Default for Scheduler<B> {
91    fn default() -> Self {
92        Self::new()
93    }
94}