celox_runtime/
scheduler.rs1use 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
20impl<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 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}