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    }
50}
51
52pub struct Scheduler<B: SimBackend> {
53    pub time: u64,
54    pub clocks: Vec<Option<ClockDef>>,
55    pub event_queue: BinaryHeap<SimEvent<B>>,
56}
57
58impl<B: SimBackend> Scheduler<B> {
59    pub fn new() -> Self {
60        Self {
61            time: 0,
62            clocks: Vec::new(),
63            event_queue: BinaryHeap::new(),
64        }
65    }
66
67    pub fn next_event_time(&self) -> Option<u64> {
68        self.event_queue.peek().map(|e| e.time)
69    }
70
71    pub fn push(&mut self, event: SimEvent<B>) {
72        self.event_queue.push(event);
73    }
74
75    pub fn pop_all_at_next_time(&mut self) -> Option<(u64, Vec<SimEvent<B>>)> {
76        let next_time = self.next_event_time()?;
77        let mut events = Vec::new();
78        while let Some(ev) = self.event_queue.peek() {
79            if ev.time == next_time {
80                events.push(self.event_queue.pop().unwrap());
81            } else {
82                break;
83            }
84        }
85        Some((next_time, events))
86    }
87}
88
89impl<B: SimBackend> Default for Scheduler<B> {
90    fn default() -> Self {
91        Self::new()
92    }
93}