1use std::cell::RefCell;
4use std::future::Future;
5use std::rc::Rc;
6
7use gwr_track::entity::{Entity, toplevel};
8use gwr_track::tracker::stdout_tracker;
9use gwr_track::{Tracker, trace};
10
11use crate::executor::{self, Executor, Spawner};
12use crate::time::clock::Clock;
13use crate::types::{Component, Eventable, SimResult};
14
15const DEFAULT_CLOCK_MHZ: f64 = 1000.0;
17
18pub struct Registry {
25 entity: Rc<Entity>,
26 components: RefCell<Vec<Component>>,
27}
28
29impl Registry {
30 fn new(parent: &Rc<Entity>) -> Self {
31 Self {
32 entity: Rc::new(Entity::new(parent, "registry")),
33 components: RefCell::new(Vec::new()),
34 }
35 }
36
37 pub fn spawn_components(&self, spawner: &Spawner) {
38 let mut guard = self.components.borrow_mut();
39
40 trace!(self.entity ; "Spawning {} components", guard.len());
41
42 for component in guard.drain(..) {
43 spawner.spawn(async move { component.run().await });
44 }
45 }
46
47 pub fn register(&self, component: Component) {
48 let mut guard = self.components.borrow_mut();
49 guard.push(component);
50 }
51}
52
53pub struct Engine {
66 pub executor: Executor,
67 spawner: Spawner,
68 toplevel: Rc<Entity>,
69 tracker: Tracker,
70 registry: Registry,
71}
72
73impl Engine {
74 pub fn new(tracker: &Tracker) -> Self {
76 let toplevel = toplevel(tracker, "top");
77 let (executor, spawner) = executor::new_executor_and_spawner(&toplevel);
78 let registry = Registry::new(&toplevel);
79 Self {
80 executor,
81 spawner,
82 toplevel,
83 tracker: tracker.clone(),
84 registry,
85 }
86 }
87
88 pub fn register(&self, component: Component) {
94 self.registry.register(component);
95 }
96
97 pub fn run(&mut self) -> SimResult {
98 self.registry.spawn_components(&self.spawner);
99
100 let finished = Rc::new(RefCell::new(false));
102 self.executor.run(&finished)
103 }
104
105 pub fn run_until<T: Default + Copy + 'static>(&mut self, event: Eventable<T>) -> SimResult {
106 self.registry.spawn_components(&self.spawner);
107
108 let finished = Rc::new(RefCell::new(false));
110 {
111 let finished = finished.clone();
112 self.spawner.spawn(async move {
113 event.listen().await;
114 *finished.borrow_mut() = true;
115 Ok(())
116 });
117 }
118
119 self.executor.run(&finished)
120 }
121
122 #[must_use]
123 pub fn spawner(&self) -> Spawner {
124 self.spawner.clone()
125 }
126
127 pub fn spawn(&self, future: impl Future<Output = SimResult> + 'static) {
128 self.spawner.spawn(future);
129 }
130
131 pub fn set_randomize_task_order(&self, randomize: bool) {
132 self.executor.set_randomize_task_order(randomize);
133 }
134
135 pub fn set_task_order_seed(&self, seed: u64) {
136 self.executor.set_task_order_seed(seed);
137 }
138
139 #[must_use]
140 pub fn default_clock(&mut self) -> Clock {
141 self.executor.get_clock(DEFAULT_CLOCK_MHZ)
142 }
143
144 #[must_use]
145 pub fn clock_hz(&mut self, freq_hz: f64) -> Clock {
146 self.executor.get_clock(freq_hz / 1_000_000.0)
147 }
148
149 #[must_use]
150 pub fn clock_khz(&mut self, freq_khz: f64) -> Clock {
151 self.executor.get_clock(freq_khz / 1000.0)
152 }
153
154 #[must_use]
155 pub fn clock_mhz(&mut self, freq_mhz: f64) -> Clock {
156 self.executor.get_clock(freq_mhz)
157 }
158
159 #[must_use]
160 pub fn clock_ghz(&mut self, freq_ghz: f64) -> Clock {
161 self.executor.get_clock(freq_ghz * 1000.0)
162 }
163
164 #[must_use]
165 pub fn time_now_ns(&self) -> f64 {
166 self.executor.time_now_ns()
167 }
168
169 #[must_use]
170 pub fn top(&self) -> &Rc<Entity> {
171 &self.toplevel
172 }
173
174 #[must_use]
175 pub fn tracker(&self) -> Tracker {
176 self.tracker.clone()
177 }
178}
179
180impl Default for Engine {
186 fn default() -> Self {
187 let tracker = stdout_tracker(log::Level::Info);
188 Self::new(&tracker)
189 }
190}
191
192impl Drop for Engine {
193 fn drop(&mut self) {
194 self.tracker.shutdown();
197 }
198}