gwr_engine/time/
simtime.rs1use std::rc::Rc;
8
9use gwr_track::entity::Entity;
10use gwr_track::set_time;
11
12use super::clock::Clock;
13use crate::time::clock::TaskWaker;
14
15#[derive(Clone)]
19pub struct SimTime {
20 entity: Rc<Entity>,
21
22 current_ns: f64,
23
24 clocks: Vec<Clock>,
29}
30
31impl SimTime {
32 #[must_use]
33 pub fn new(parent: &Rc<Entity>) -> Self {
34 Self {
35 entity: Rc::new(Entity::new(parent, "time")),
36 current_ns: 0.0,
37 clocks: Vec::new(),
38 }
39 }
40
41 pub fn get_clock(&mut self, freq_mhz: f64) -> Clock {
42 for clock in &self.clocks {
43 if clock.freq_mhz() == freq_mhz {
44 return clock.clone();
45 }
46 }
47 let clock = Clock::new(freq_mhz);
48 self.clocks.push(clock.clone());
49 clock
50 }
51
52 pub fn advance_time(&mut self) -> Option<Vec<TaskWaker>> {
54 if let Some(next_clock) = self.clocks.iter().min_by(|a, b| a.cmp(b)) {
55 if let Some(clock_time) = next_clock.shared_state.waiting_times.borrow_mut().pop() {
56 let next_ns = next_clock.to_ns(&clock_time);
57 if self.current_ns != next_ns {
58 set_time!(self.entity ; next_ns);
59 self.current_ns = next_ns;
60 }
61 next_clock.shared_state.waiting.borrow_mut().pop()
62 } else {
63 None
64 }
65 } else {
66 None
67 }
68 }
69
70 pub fn advance_all_clocks_to(&mut self, time_ns: f64) {
72 for clock in &self.clocks {
73 clock.advance_to(time_ns);
74 }
75 set_time!(self.entity ; time_ns);
76 self.current_ns = time_ns;
77 }
78
79 #[must_use]
80 pub fn time_now_ns(&self) -> f64 {
81 self.current_ns
82 }
83
84 #[must_use]
86 pub fn can_exit(&self) -> bool {
87 for clock in &self.clocks {
88 for waiting in clock.shared_state.waiting.borrow().iter() {
89 for task_waker in waiting {
90 if !task_waker.can_exit {
91 return false;
93 }
94 }
95 }
96 }
97 true
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use gwr_track::entity::toplevel;
104 use gwr_track::test_helpers::create_tracker;
105
106 use super::*;
107
108 #[test]
109 fn clock_created_once() {
110 let tracker = create_tracker(file!());
111 let top = toplevel(&tracker, "top");
112
113 let mut time = SimTime::new(&top);
114 let _clk1 = time.get_clock(1000.0);
115 assert_eq!(time.clocks.len(), 1);
116
117 let _clk2 = time.get_clock(1000.0);
118 assert_eq!(time.clocks.len(), 1);
119 }
120
121 #[test]
122 fn create_different_clocks() {
123 let tracker = create_tracker(file!());
124 let top = toplevel(&tracker, "top");
125
126 let mut time = SimTime::new(&top);
127 let _clk1 = time.get_clock(1000.0);
128 assert_eq!(time.clocks.len(), 1);
129
130 let _clk2 = time.get_clock(1800.0);
131 assert_eq!(time.clocks.len(), 2);
132 }
133}