1use std::sync::Mutex;
2
3use chrono::prelude::{DateTime, Utc};
4use color_eyre::{eyre::bail, Result};
5use num::BigUint;
6use serde::{Deserialize, Serialize};
7use surfer_translation_types::VariableValue;
8
9use crate::cxxrtl_container::CxxrtlContainer;
10use crate::time::{TimeScale, TimeUnit};
11use crate::wellen::{BodyResult, LoadSignalsCmd, LoadSignalsResult, WellenContainer};
12
13pub type FieldRef = surfer_translation_types::FieldRef<VarId, ScopeId>;
14pub type ScopeRef = surfer_translation_types::ScopeRef<ScopeId>;
15pub type VariableRef = surfer_translation_types::VariableRef<VarId, ScopeId>;
16pub type VariableMeta = surfer_translation_types::VariableMeta<VarId, ScopeId>;
17
18#[derive(Debug, Clone)]
19pub enum SimulationStatus {
20 Paused,
21 Running,
22 Finished,
23}
24
25pub struct MetaData {
26 pub date: Option<DateTime<Utc>>,
27 pub version: Option<String>,
28 pub timescale: TimeScale,
29}
30
31#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
33pub enum ScopeId {
34 None,
35 Wellen(wellen::ScopeRef),
36}
37
38impl Default for ScopeId {
39 fn default() -> Self {
40 Self::None
41 }
42}
43
44#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
46pub enum VarId {
47 None,
48 Wellen(wellen::VarRef),
49}
50
51impl Default for VarId {
52 fn default() -> Self {
53 Self::None
54 }
55}
56
57#[derive(Debug, Default)]
58pub struct QueryResult {
59 pub current: Option<(BigUint, VariableValue)>,
60 pub next: Option<BigUint>,
61}
62
63#[local_impl::local_impl]
64impl ScopeRefExt for ScopeRef {
65 fn empty() -> Self {
66 Self {
67 strs: vec![],
68 id: ScopeId::default(),
69 }
70 }
71
72 fn from_strs<S: ToString>(s: &[S]) -> Self {
73 Self::from_strs_with_id(s, ScopeId::default())
74 }
75
76 fn from_strs_with_id(s: &[impl ToString], id: ScopeId) -> Self {
77 let strs = s.iter().map(std::string::ToString::to_string).collect();
78 Self { strs, id }
79 }
80
81 fn from_hierarchy_string(s: &str) -> Self {
83 let strs = s.split('.').map(std::string::ToString::to_string).collect();
84 let id = ScopeId::default();
85 Self { strs, id }
86 }
87
88 fn with_subscope(&self, subscope: String, id: ScopeId) -> Self {
89 let mut result = self.clone();
90 result.strs.push(subscope);
91 result.id = id;
93 result
94 }
95
96 fn name(&self) -> String {
97 self.strs.last().cloned().unwrap_or_default()
98 }
99
100 fn strs(&self) -> &[String] {
101 &self.strs
102 }
103
104 fn with_id(&self, id: ScopeId) -> Self {
105 let mut out = self.clone();
106 out.id = id;
107 out
108 }
109
110 fn cxxrtl_repr(&self) -> String {
111 self.strs.join(" ")
112 }
113
114 fn has_empty_strs(&self) -> bool {
115 self.strs.is_empty()
116 }
117}
118
119#[local_impl::local_impl]
120impl VariableRefExt for VariableRef {
121 fn new(path: ScopeRef, name: String) -> Self {
122 Self::new_with_id(path, name, VarId::default())
123 }
124
125 fn new_with_id(path: ScopeRef, name: String, id: VarId) -> Self {
126 Self { path, name, id }
127 }
128
129 fn from_hierarchy_string(s: &str) -> Self {
130 let components = s
131 .split('.')
132 .map(std::string::ToString::to_string)
133 .collect::<Vec<_>>();
134
135 if components.is_empty() {
136 Self {
137 path: ScopeRef::empty(),
138 name: String::new(),
139 id: VarId::default(),
140 }
141 } else {
142 Self {
143 path: ScopeRef::from_strs(&components[..(components.len()) - 1]),
144 name: components.last().unwrap().to_string(),
145 id: VarId::default(),
146 }
147 }
148 }
149
150 fn full_path_string(&self) -> String {
152 if self.path.has_empty_strs() {
153 self.name.clone()
154 } else {
155 format!("{}.{}", self.path, self.name)
156 }
157 }
158
159 fn full_path(&self) -> Vec<String> {
160 self.path
161 .strs()
162 .iter()
163 .cloned()
164 .chain([self.name.clone()])
165 .collect()
166 }
167
168 fn from_strs(s: &[&str]) -> Self {
169 Self {
170 path: ScopeRef::from_strs(&s[..(s.len() - 1)]),
171 name: s
172 .last()
173 .expect("from_strs called with an empty string")
174 .to_string(),
175 id: VarId::default(),
176 }
177 }
178
179 fn clear_id(&mut self) {
180 self.id = VarId::default();
181 }
182
183 fn cxxrtl_repr(&self) -> String {
184 self.full_path().join(" ")
185 }
186}
187
188#[local_impl::local_impl]
189impl FieldRefExt for FieldRef {
190 fn without_fields(root: VariableRef) -> Self {
191 Self {
192 root,
193 field: vec![],
194 }
195 }
196
197 fn from_strs(root: &[&str], field: &[&str]) -> Self {
198 Self {
199 root: VariableRef::from_strs(root),
200 field: field.iter().map(std::string::ToString::to_string).collect(),
201 }
202 }
203}
204
205pub enum WaveContainer {
206 Wellen(Box<WellenContainer>),
207 Empty,
210 Cxxrtl(Box<Mutex<CxxrtlContainer>>),
211}
212
213impl WaveContainer {
214 pub fn new_waveform(hierarchy: std::sync::Arc<wellen::Hierarchy>) -> Self {
215 WaveContainer::Wellen(Box::new(WellenContainer::new(hierarchy, None)))
216 }
217
218 pub fn new_remote_waveform(
219 server_url: String,
220 hierarchy: std::sync::Arc<wellen::Hierarchy>,
221 ) -> Self {
222 WaveContainer::Wellen(Box::new(WellenContainer::new(hierarchy, Some(server_url))))
223 }
224
225 pub fn __new_empty() -> Self {
229 WaveContainer::Empty
230 }
231
232 pub fn tick(&self) {
234 match self {
235 WaveContainer::Wellen(_) => {}
236 WaveContainer::Empty => {}
237 WaveContainer::Cxxrtl(c) => c.lock().unwrap().tick(),
238 }
239 }
240
241 pub fn wants_anti_aliasing(&self) -> bool {
242 match self {
243 WaveContainer::Wellen(_) => true,
244 WaveContainer::Empty => true,
245 WaveContainer::Cxxrtl(_) => true,
247 }
248 }
249
250 pub fn is_fully_loaded(&self) -> bool {
254 match self {
255 WaveContainer::Wellen(f) => f.is_fully_loaded(),
256 WaveContainer::Empty => true,
257 WaveContainer::Cxxrtl(_) => true,
258 }
259 }
260
261 pub fn variable_names(&self) -> Vec<String> {
263 match self {
264 WaveContainer::Wellen(f) => f.variable_names(),
265 WaveContainer::Empty => vec![],
266 WaveContainer::Cxxrtl(_) => vec![], }
269 }
270
271 pub fn variables(&self) -> Vec<VariableRef> {
272 match self {
273 WaveContainer::Wellen(f) => f.variables(),
274 WaveContainer::Empty => vec![],
275 WaveContainer::Cxxrtl(_) => vec![],
276 }
277 }
278
279 pub fn variables_in_scope(&self, scope: &ScopeRef) -> Vec<VariableRef> {
281 match self {
282 WaveContainer::Wellen(f) => f.variables_in_scope(scope),
283 WaveContainer::Empty => vec![],
284 WaveContainer::Cxxrtl(c) => c.lock().unwrap().variables_in_module(scope),
285 }
286 }
287
288 pub fn parameters_in_scope(&self, scope: &ScopeRef) -> Vec<VariableRef> {
290 match self {
291 WaveContainer::Wellen(f) => f.parameters_in_scope(scope),
292 WaveContainer::Empty => vec![],
293 WaveContainer::Cxxrtl(_) => vec![],
295 }
296 }
297
298 pub fn no_variables_in_scope(&self, scope: &ScopeRef) -> bool {
300 match self {
301 WaveContainer::Wellen(f) => f.no_variables_in_scope(scope),
302 WaveContainer::Empty => true,
303 WaveContainer::Cxxrtl(c) => c.lock().unwrap().no_variables_in_module(scope),
304 }
305 }
306
307 pub fn load_variables<S: AsRef<VariableRef>, T: Iterator<Item = S>>(
309 &mut self,
310 variables: T,
311 ) -> Result<Option<LoadSignalsCmd>> {
312 match self {
313 WaveContainer::Wellen(f) => f.load_variables(variables),
314 WaveContainer::Empty => bail!("Cannot load variables from empty container."),
315 WaveContainer::Cxxrtl(c) => {
316 c.get_mut().unwrap().load_variables(variables);
317 Ok(None)
318 }
319 }
320 }
321 pub fn load_parameters(&mut self) -> Result<Option<LoadSignalsCmd>> {
323 match self {
324 WaveContainer::Wellen(f) => f.load_all_params(),
325 WaveContainer::Empty => bail!("Cannot load parameters from empty container."),
326 WaveContainer::Cxxrtl(_) => {
327 Ok(None)
329 }
330 }
331 }
332
333 pub fn on_signals_loaded(&mut self, res: LoadSignalsResult) -> Result<Option<LoadSignalsCmd>> {
336 match self {
337 WaveContainer::Wellen(f) => f.on_signals_loaded(res),
338 WaveContainer::Empty => {
339 bail!("on_load_signals should only be called with the wellen backend.")
340 }
341 WaveContainer::Cxxrtl(_) => {
342 bail!("on_load_signals should only be called with the wellen backend.")
343 }
344 }
345 }
346
347 pub fn variable_meta<'a>(&'a self, variable: &'a VariableRef) -> Result<VariableMeta> {
348 match self {
349 WaveContainer::Wellen(f) => f.variable_to_meta(variable),
350 WaveContainer::Empty => bail!("Getting meta from empty wave container"),
351 WaveContainer::Cxxrtl(c) => c.lock().unwrap().variable_meta(variable),
352 }
353 }
354
355 pub fn query_variable(
359 &self,
360 variable: &VariableRef,
361 time: &BigUint,
362 ) -> Result<Option<QueryResult>> {
363 match self {
364 WaveContainer::Wellen(f) => f.query_variable(variable, time),
365 WaveContainer::Empty => bail!("Querying variable from empty wave container"),
366 WaveContainer::Cxxrtl(c) => Ok(c.lock().unwrap().query_variable(variable, time)),
367 }
368 }
369
370 pub fn update_variable_ref(&self, variable: &VariableRef) -> Option<VariableRef> {
372 match self {
373 WaveContainer::Wellen(f) => f.update_variable_ref(variable),
374 WaveContainer::Empty => None,
375 WaveContainer::Cxxrtl(_) => None,
376 }
377 }
378
379 pub fn scope_names(&self) -> Vec<String> {
381 match self {
382 WaveContainer::Wellen(f) => f.scope_names(),
383 WaveContainer::Empty => vec![],
384 WaveContainer::Cxxrtl(c) => c
385 .lock()
386 .unwrap()
387 .modules()
388 .iter()
389 .map(|m| m.strs().last().cloned().unwrap_or("root".to_string()))
390 .collect(),
391 }
392 }
393
394 pub fn metadata(&self) -> MetaData {
395 match self {
396 WaveContainer::Wellen(f) => f.metadata(),
397 WaveContainer::Empty => MetaData {
398 date: None,
399 version: None,
400 timescale: TimeScale {
401 unit: TimeUnit::None,
402 multiplier: None,
403 },
404 },
405 WaveContainer::Cxxrtl(_) => {
406 MetaData {
407 date: None,
408 version: None,
409 timescale: TimeScale {
410 unit: TimeUnit::FemtoSeconds,
412 multiplier: None,
413 },
414 }
415 }
416 }
417 }
418
419 pub fn root_scopes(&self) -> Vec<ScopeRef> {
420 match self {
421 WaveContainer::Wellen(f) => f.root_scopes(),
422 WaveContainer::Empty => vec![],
423 WaveContainer::Cxxrtl(c) => c.lock().unwrap().root_modules(),
424 }
425 }
426
427 pub fn child_scopes(&self, scope: &ScopeRef) -> Result<Vec<ScopeRef>> {
428 match self {
429 WaveContainer::Wellen(f) => f.child_scopes(scope),
430 WaveContainer::Empty => bail!("Getting child modules from empty wave container"),
431 WaveContainer::Cxxrtl(c) => Ok(c.lock().unwrap().child_scopes(scope)),
432 }
433 }
434
435 pub fn max_timestamp(&self) -> Option<BigUint> {
436 match self {
437 WaveContainer::Wellen(f) => f.max_timestamp(),
438 WaveContainer::Empty => None,
439 WaveContainer::Cxxrtl(c) => c
440 .lock()
441 .unwrap()
442 .max_displayed_timestamp()
443 .map(|t| t.as_femtoseconds()),
444 }
445 }
446
447 pub fn scope_exists(&self, scope: &ScopeRef) -> bool {
448 match self {
449 WaveContainer::Wellen(f) => f.scope_exists(scope),
450 WaveContainer::Empty => false,
451 WaveContainer::Cxxrtl(c) => c.lock().unwrap().module_exists(scope),
452 }
453 }
454
455 pub fn get_scope_tooltip_data(&self, scope: &ScopeRef) -> String {
458 match self {
459 WaveContainer::Wellen(f) => f.get_scope_tooltip_data(scope),
460 WaveContainer::Empty => String::new(),
461 WaveContainer::Cxxrtl(_) => String::new(),
463 }
464 }
465
466 pub fn simulation_status(&self) -> Option<SimulationStatus> {
470 match self {
471 WaveContainer::Wellen(_) => None,
472 WaveContainer::Empty => None,
473 WaveContainer::Cxxrtl(c) => c.lock().unwrap().simulation_status(),
474 }
475 }
476
477 pub fn unpause_simulation(&self) {
480 match self {
481 WaveContainer::Wellen(_) => {}
482 WaveContainer::Empty => {}
483 WaveContainer::Cxxrtl(c) => c.lock().unwrap().unpause(),
484 }
485 }
486
487 pub fn pause_simulation(&self) {
489 match self {
490 WaveContainer::Wellen(_) => {}
491 WaveContainer::Empty => {}
492 WaveContainer::Cxxrtl(c) => c.lock().unwrap().pause(),
493 }
494 }
495
496 pub fn wellen_add_body(&mut self, body: BodyResult) -> Result<Option<LoadSignalsCmd>> {
498 match self {
499 WaveContainer::Wellen(inner) => inner.add_body(body),
500 _ => {
501 bail!("Should never call this function on a non wellen container!")
502 }
503 }
504 }
505
506 pub fn body_loaded(&self) -> bool {
507 match self {
508 WaveContainer::Wellen(inner) => inner.body_loaded(),
509 WaveContainer::Empty => true,
510 WaveContainer::Cxxrtl(_) => true,
511 }
512 }
513}