use crate::{
SignalRef,
backend::{EventHandle, SimBackend},
};
use std::collections::BinaryHeap;
#[derive(Debug, Clone)]
pub struct ClockDef {
pub period: u64,
}
#[derive(Debug, Clone)]
pub struct SimEvent<B: SimBackend> {
pub time: u64,
pub event_ref: B::Event,
pub signal: SignalRef,
pub next_val: u8,
}
impl<B: SimBackend> PartialEq for SimEvent<B> {
fn eq(&self, other: &Self) -> bool {
self.time == other.time
&& self.event_ref.addr() == other.event_ref.addr()
&& self.signal == other.signal
&& self.next_val == other.next_val
}
}
impl<B: SimBackend> Eq for SimEvent<B> {}
impl<B: SimBackend> PartialOrd for SimEvent<B> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<B: SimBackend> Ord for SimEvent<B> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
other
.time
.cmp(&self.time)
.then_with(|| {
let id1 = self.event_ref.id();
let id2 = other.event_ref.id();
id2.cmp(&id1)
})
.then_with(|| other.signal.cmp(&self.signal))
}
}
pub struct Scheduler<B: SimBackend> {
pub time: u64,
pub clocks: Vec<Option<ClockDef>>,
pub event_queue: BinaryHeap<SimEvent<B>>,
}
impl<B: SimBackend> Scheduler<B> {
pub fn new() -> Self {
Self {
time: 0,
clocks: Vec::new(),
event_queue: BinaryHeap::new(),
}
}
pub fn next_event_time(&self) -> Option<u64> {
self.event_queue.peek().map(|e| e.time)
}
pub fn push(&mut self, event: SimEvent<B>) {
self.event_queue.push(event);
}
pub fn pop_all_at_next_time(&mut self) -> Option<(u64, Vec<SimEvent<B>>)> {
let next_time = self.next_event_time()?;
let mut events = Vec::new();
while let Some(ev) = self.event_queue.peek() {
if ev.time == next_time {
events.push(self.event_queue.pop().unwrap());
} else {
break;
}
}
Some((next_time, events))
}
}
impl<B: SimBackend> Default for Scheduler<B> {
fn default() -> Self {
Self::new()
}
}