1use std::sync::Mutex;
2
3use chrono::prelude::{DateTime, Utc};
4use eyre::{Result, bail};
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
18pub type AnalogCacheKey = (SignalId, String);
20
21#[derive(Debug, Clone)]
22pub enum SimulationStatus {
23 Paused,
24 Running,
25 Finished,
26}
27
28pub struct MetaData {
29 pub date: Option<DateTime<Utc>>,
30 pub version: Option<String>,
31 pub timescale: TimeScale,
32}
33
34#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
36pub enum ScopeId {
37 #[default]
38 None,
39 Wellen(wellen::ScopeRef),
40}
41
42#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
44pub enum VarId {
45 #[default]
46 None,
47 Wellen(wellen::VarRef),
48}
49
50#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
53pub enum SignalId {
54 #[default]
55 None,
56 Wellen(wellen::SignalRef),
57}
58
59pub enum SignalAccessor {
62 Wellen(crate::wellen::WellenSignalAccessor),
63 }
65
66impl SignalAccessor {
67 #[must_use]
69 pub fn iter_changes(&self) -> Box<dyn Iterator<Item = (u64, VariableValue)> + '_> {
70 match self {
71 SignalAccessor::Wellen(accessor) => accessor.iter_changes(),
72 }
73 }
74}
75
76#[derive(Debug, Default)]
77pub struct QueryResult {
78 pub current: Option<(BigUint, VariableValue)>,
79 pub next: Option<BigUint>,
80}
81
82#[local_impl::local_impl]
83impl ScopeRefExt for ScopeRef {
84 fn empty() -> Self {
85 Self {
86 strs: vec![],
87 id: ScopeId::default(),
88 }
89 }
90
91 fn from_strs<S: ToString>(s: &[S]) -> Self {
92 Self::from_strs_with_id(s, ScopeId::default())
93 }
94
95 fn from_strs_with_id(s: &[impl ToString], id: ScopeId) -> Self {
96 let strs = s.iter().map(ToString::to_string).collect();
97 Self { strs, id }
98 }
99
100 fn from_hierarchy_string(s: &str) -> Self {
102 let strs = s.split('.').map(ToString::to_string).collect();
103 let id = ScopeId::default();
104 Self { strs, id }
105 }
106
107 fn with_subscope(&self, subscope: String, id: ScopeId) -> Self {
108 let mut result = self.clone();
109 result.strs.push(subscope);
110 result.id = id;
112 result
113 }
114
115 fn name(&self) -> String {
116 self.strs.last().cloned().unwrap_or_default()
117 }
118
119 fn full_name(&self) -> String {
120 self.strs.join(".")
121 }
122
123 fn strs(&self) -> &[String] {
124 &self.strs
125 }
126
127 fn with_id(&self, id: ScopeId) -> Self {
128 let mut out = self.clone();
129 out.id = id;
130 out
131 }
132
133 fn cxxrtl_repr(&self) -> String {
134 self.strs.join(" ")
135 }
136
137 fn has_empty_strs(&self) -> bool {
138 self.strs.is_empty()
139 }
140}
141
142fn extract_index(s: &str) -> (String, Option<i64>) {
143 if let Some(start_idx) = s.rfind('[')
144 && start_idx > 0
145 && s.ends_with(']')
146 {
147 let index_str = &s[start_idx + 1..s.len() - 1];
148 if let Ok(index) = index_str.parse::<i64>() {
149 let name = s[..start_idx].to_string();
150 return (name, Some(index));
151 }
152 }
153 (s.to_string(), None)
154}
155
156#[local_impl::local_impl]
157impl VariableRefExt for VariableRef {
158 fn new(path: ScopeRef, name: String) -> Self {
159 Self::new_with_id_and_index(path, name, VarId::default(), None)
160 }
161
162 fn new_with_id_and_index(path: ScopeRef, name: String, id: VarId, index: Option<i64>) -> Self {
163 let (name, index) = if index.is_none() {
164 extract_index(&name)
165 } else {
166 (name, index)
167 };
168 Self {
169 path,
170 name,
171 id,
172 index,
173 }
174 }
175
176 fn from_hierarchy_string(s: &str) -> Self {
177 let components = s.split('.').map(ToString::to_string).collect::<Vec<_>>();
178
179 if components.is_empty() {
180 Self {
181 path: ScopeRef::empty(),
182 name: String::new(),
183 id: VarId::default(),
184 index: None,
185 }
186 } else {
187 let name = components.last().unwrap();
188 let (name, index) = extract_index(name);
189 Self {
190 path: ScopeRef::from_strs(&components[..(components.len()) - 1]),
191 name,
192 id: VarId::default(),
193 index,
194 }
195 }
196 }
197
198 fn from_hierarchy_string_with_id(s: &str, id: VarId) -> Self {
199 let components = s
200 .split('.')
201 .map(std::string::ToString::to_string)
202 .collect::<Vec<_>>();
203
204 if components.is_empty() {
205 Self {
206 path: ScopeRef::empty(),
207 name: String::new(),
208 id,
209 index: None,
210 }
211 } else {
212 Self {
213 path: ScopeRef::from_strs(&components[..(components.len()) - 1]),
214 name: components.last().unwrap().clone(),
215 id,
216 index: None,
217 }
218 }
219 }
220
221 fn full_path_string_no_index(&self) -> String {
223 if self.path.has_empty_strs() {
224 self.name.clone()
225 } else {
226 format!("{}.{}", self.path, self.name)
227 }
228 }
229
230 fn full_path_string(&self) -> String {
232 if let Some(index) = self.index {
233 format!("{}.{}[{}]", self.path, self.name, index)
234 } else {
235 self.full_path_string_no_index()
236 }
237 }
238
239 fn full_path(&self) -> Vec<String> {
241 self.path
242 .strs()
243 .iter()
244 .cloned()
245 .chain([self.name.clone()])
246 .collect()
247 }
248
249 fn full_path_with_index(&self) -> Vec<String> {
251 if let Some(index) = self.index {
252 self.path
253 .strs()
254 .iter()
255 .cloned()
256 .chain([self.name.clone(), format!("[{index}]")])
257 .collect()
258 } else {
259 self.full_path()
260 }
261 }
262
263 fn from_strs(s: &[&str]) -> Self {
264 Self {
265 path: ScopeRef::from_strs(&s[..(s.len() - 1)]),
266 name: (*s.last().expect("from_strs called with an empty string")).to_string(),
267 id: VarId::default(),
268 index: None,
269 }
270 }
271
272 fn clear_id(&mut self) {
273 self.id = VarId::default();
274 }
275
276 fn cxxrtl_repr(&self) -> String {
277 self.full_path().join(" ")
278 }
279}
280
281#[local_impl::local_impl]
282impl FieldRefExt for FieldRef {
283 fn without_fields(root: VariableRef) -> Self {
284 Self {
285 root,
286 field: vec![],
287 }
288 }
289
290 fn from_strs(root: &[&str], field: &[&str]) -> Self {
291 Self {
292 root: VariableRef::from_strs(root),
293 field: field.iter().map(ToString::to_string).collect(),
294 }
295 }
296}
297
298pub enum WaveContainer {
299 Wellen(Box<WellenContainer>),
300 Empty,
305 Cxxrtl(Box<Mutex<CxxrtlContainer>>),
306}
307
308impl WaveContainer {
309 #[must_use]
310 pub fn new_waveform(hierarchy: std::sync::Arc<wellen::Hierarchy>) -> Self {
311 WaveContainer::Wellen(Box::new(WellenContainer::new(hierarchy, None, None)))
312 }
313
314 #[must_use]
315 pub fn new_remote_waveform(
316 server_url: &str,
317 hierarchy: std::sync::Arc<wellen::Hierarchy>,
318 file_index: usize,
319 ) -> Self {
320 WaveContainer::Wellen(Box::new(WellenContainer::new(
321 hierarchy,
322 Some(server_url.to_string()),
323 Some(file_index),
324 )))
325 }
326
327 #[must_use]
332 pub fn __new_empty() -> Self {
333 WaveContainer::Empty
334 }
335
336 pub fn tick(&self) {
338 match self {
339 WaveContainer::Wellen(_) => {}
340 WaveContainer::Empty => {}
341 WaveContainer::Cxxrtl(c) => c.lock().unwrap().tick(),
342 }
343 }
344
345 #[must_use]
346 pub fn wants_anti_aliasing(&self) -> bool {
347 match self {
348 WaveContainer::Wellen(_) => true,
349 WaveContainer::Empty => true,
350 WaveContainer::Cxxrtl(_) => true,
352 }
353 }
354
355 #[must_use]
359 pub fn is_fully_loaded(&self) -> bool {
360 match self {
361 WaveContainer::Wellen(f) => f.is_fully_loaded(),
362 WaveContainer::Empty => true,
363 WaveContainer::Cxxrtl(_) => true,
364 }
365 }
366
367 #[must_use]
369 pub fn variable_names(&self) -> Vec<String> {
370 match self {
371 WaveContainer::Wellen(f) => f.variable_names(),
372 WaveContainer::Empty => vec![],
373 WaveContainer::Cxxrtl(_) => vec![], }
376 }
377
378 #[must_use]
380 pub fn variables(&self) -> Vec<VariableRef> {
381 match self {
382 WaveContainer::Wellen(f) => f.variables(),
383 WaveContainer::Empty => vec![],
384 WaveContainer::Cxxrtl(_) => vec![],
385 }
386 }
387
388 #[must_use]
390 pub fn variables_in_scope(&self, scope: &ScopeRef) -> Vec<VariableRef> {
391 match self {
392 WaveContainer::Wellen(f) => f.variables_in_scope(scope),
393 WaveContainer::Empty => vec![],
394 WaveContainer::Cxxrtl(c) => c.lock().unwrap().variables_in_module(scope),
395 }
396 }
397
398 #[must_use]
400 pub fn parameters_in_scope(&self, scope: &ScopeRef) -> Vec<VariableRef> {
401 match self {
402 WaveContainer::Wellen(f) => f.parameters_in_scope(scope),
403 WaveContainer::Empty => vec![],
404 WaveContainer::Cxxrtl(_) => vec![],
406 }
407 }
408
409 #[must_use]
411 pub fn no_variables_in_scope(&self, scope: &ScopeRef) -> bool {
412 match self {
413 WaveContainer::Wellen(f) => f.no_variables_in_scope(scope),
414 WaveContainer::Empty => true,
415 WaveContainer::Cxxrtl(c) => c.lock().unwrap().no_variables_in_module(scope),
416 }
417 }
418
419 pub fn load_variables<S: AsRef<VariableRef>, T: Iterator<Item = S>>(
423 &mut self,
424 variables: T,
425 ) -> Result<Option<LoadSignalsCmd>> {
426 match self {
427 WaveContainer::Wellen(f) => f.load_variables(variables),
428 WaveContainer::Empty => {
429 bail!("Cannot load variables from empty container.");
430 }
431 WaveContainer::Cxxrtl(c) => {
432 c.get_mut().unwrap().load_variables(variables);
433 Ok(None)
434 }
435 }
436 }
437 pub fn load_parameters(&mut self) -> Result<Option<LoadSignalsCmd>> {
439 match self {
440 WaveContainer::Wellen(f) => f.load_all_params(),
441 WaveContainer::Empty => {
442 bail!("Cannot load parameters from empty container.");
443 }
444 WaveContainer::Cxxrtl(_) => {
445 Ok(None)
447 }
448 }
449 }
450
451 pub fn on_signals_loaded(&mut self, res: LoadSignalsResult) -> Result<Option<LoadSignalsCmd>> {
456 match self {
457 WaveContainer::Wellen(f) => f.on_signals_loaded(res),
458 WaveContainer::Empty => {
459 bail!("on_load_signals should only be called with the wellen backend.");
460 }
461 WaveContainer::Cxxrtl(_) => {
462 bail!("on_load_signals should only be called with the wellen backend.");
463 }
464 }
465 }
466
467 pub fn variable_meta<'a>(&'a self, variable: &'a VariableRef) -> Result<VariableMeta> {
468 match self {
469 WaveContainer::Wellen(f) => f.variable_to_meta(variable),
470 WaveContainer::Empty => {
471 bail!("Getting meta from empty wave container");
472 }
473 WaveContainer::Cxxrtl(c) => c.lock().unwrap().variable_meta(variable),
474 }
475 }
476
477 pub fn query_variable(
481 &self,
482 variable: &VariableRef,
483 time: &BigUint,
484 ) -> Result<Option<QueryResult>> {
485 match self {
486 WaveContainer::Wellen(f) => f.query_variable(variable, time),
487 WaveContainer::Empty => {
488 bail!("Querying variable from empty wave container");
489 }
490 WaveContainer::Cxxrtl(c) => Ok(c.lock().unwrap().query_variable(variable, time)),
491 }
492 }
493
494 pub fn signal_accessor(&self, signal_id: SignalId) -> Result<SignalAccessor> {
495 match (self, signal_id) {
496 (WaveContainer::Wellen(f), SignalId::Wellen(signal_ref)) => {
497 Ok(SignalAccessor::Wellen(f.signal_accessor(signal_ref)?))
498 }
499 _ => {
500 bail!("Invalid signal accessor combination");
501 }
502 }
503 }
504 pub fn signal_id(&self, variable: &VariableRef) -> Result<SignalId> {
506 match self {
507 WaveContainer::Wellen(f) => Ok(SignalId::Wellen(f.signal_ref(variable)?)),
508 WaveContainer::Empty => {
509 bail!("No signal data");
510 }
511 WaveContainer::Cxxrtl(_) => {
512 bail!("Not supported for Cxxrtl yet");
513 }
514 }
515 }
516
517 #[must_use]
519 pub fn is_signal_loaded(&self, signal_id: &SignalId) -> bool {
520 match (self, signal_id) {
521 (WaveContainer::Wellen(f), SignalId::Wellen(signal_ref)) => {
522 f.is_signal_loaded(*signal_ref)
523 }
524 _ => false,
525 }
526 }
527
528 #[must_use]
530 pub fn update_variable_ref(&self, variable: &VariableRef) -> Option<VariableRef> {
531 match self {
532 WaveContainer::Wellen(f) => f.update_variable_ref(variable),
533 WaveContainer::Empty => None,
534 WaveContainer::Cxxrtl(_) => None,
535 }
536 }
537
538 #[must_use]
540 pub fn scope_names(&self) -> Vec<String> {
541 match self {
542 WaveContainer::Wellen(f) => f.scope_names(),
543 WaveContainer::Empty => vec![],
544 WaveContainer::Cxxrtl(c) => c
545 .lock()
546 .unwrap()
547 .modules()
548 .iter()
549 .map(|m| m.strs().last().cloned().unwrap_or("root".to_string()))
550 .collect(),
551 }
552 }
553
554 #[must_use]
556 pub fn array_names(&self) -> Vec<String> {
557 match self {
558 WaveContainer::Wellen(f) => f.array_scope_names(),
559 WaveContainer::Empty => vec![],
560 WaveContainer::Cxxrtl(_) => vec![],
561 }
562 }
563
564 #[must_use]
565 pub fn metadata(&self) -> MetaData {
566 match self {
567 WaveContainer::Wellen(f) => f.metadata(),
568 WaveContainer::Empty => MetaData {
569 date: None,
570 version: None,
571 timescale: TimeScale {
572 unit: TimeUnit::None,
573 multiplier: None,
574 },
575 },
576 WaveContainer::Cxxrtl(_) => {
577 MetaData {
578 date: None,
579 version: None,
580 timescale: TimeScale {
581 unit: TimeUnit::FemtoSeconds,
583 multiplier: None,
584 },
585 }
586 }
587 }
588 }
589
590 #[must_use]
591 pub fn root_scopes(&self) -> Vec<ScopeRef> {
592 match self {
593 WaveContainer::Wellen(f) => f.root_scopes(),
594 WaveContainer::Empty => vec![],
595 WaveContainer::Cxxrtl(c) => c.lock().unwrap().root_modules(),
596 }
597 }
598
599 pub fn child_scopes(&self, scope: &ScopeRef) -> Result<Vec<ScopeRef>> {
600 match self {
601 WaveContainer::Wellen(f) => f.child_scopes(scope),
602 WaveContainer::Empty => {
603 bail!("Getting child modules from empty wave container");
604 }
605 WaveContainer::Cxxrtl(c) => Ok(c.lock().unwrap().child_scopes(scope)),
606 }
607 }
608
609 #[must_use]
610 pub fn max_timestamp(&self) -> Option<BigUint> {
611 match self {
612 WaveContainer::Wellen(f) => f.max_timestamp(),
613 WaveContainer::Empty => None,
614 WaveContainer::Cxxrtl(c) => c
615 .lock()
616 .unwrap()
617 .max_displayed_timestamp()
618 .map(|t| t.as_femtoseconds()),
619 }
620 }
621 #[must_use]
622 pub fn min_timestamp(&self) -> Option<BigUint> {
623 match self {
624 WaveContainer::Wellen(f) => f.min_timestamp(),
625 WaveContainer::Empty => None,
626 WaveContainer::Cxxrtl(_) => None,
627 }
628 }
629
630 #[must_use]
631 pub fn scope_exists(&self, scope: &ScopeRef) -> bool {
632 match self {
633 WaveContainer::Wellen(f) => f.scope_exists(scope),
634 WaveContainer::Empty => false,
635 WaveContainer::Cxxrtl(c) => c.lock().unwrap().module_exists(scope),
636 }
637 }
638
639 #[must_use]
640 pub fn scope_is_variable(&self, scope: &ScopeRef) -> bool {
642 match self {
643 WaveContainer::Wellen(f) => f.scope_is_variable(scope),
644 WaveContainer::Empty => false,
645 WaveContainer::Cxxrtl(_) => false, }
647 }
648
649 #[must_use]
650 pub fn scope_is_array(&self, scope: &ScopeRef) -> bool {
652 match self {
653 WaveContainer::Wellen(f) => f.scope_is_array(scope),
654 WaveContainer::Empty => false,
655 WaveContainer::Cxxrtl(_) => false, }
657 }
658
659 #[must_use]
662 pub fn get_scope_tooltip_data(&self, scope: &ScopeRef) -> String {
663 match self {
664 WaveContainer::Wellen(f) => f.get_scope_tooltip_data(scope),
665 WaveContainer::Empty => String::new(),
666 WaveContainer::Cxxrtl(_) => String::new(),
668 }
669 }
670
671 #[must_use]
674 pub fn get_scope_type(&self, scope: &ScopeRef) -> Option<wellen::ScopeType> {
675 match self {
676 WaveContainer::Wellen(f) => f.get_scope_type(scope),
677 WaveContainer::Empty | WaveContainer::Cxxrtl(_) => None,
678 }
679 }
680
681 #[must_use]
686 pub fn simulation_status(&self) -> Option<SimulationStatus> {
687 match self {
688 WaveContainer::Wellen(_) => None,
689 WaveContainer::Empty => None,
690 WaveContainer::Cxxrtl(c) => c.lock().unwrap().simulation_status(),
691 }
692 }
693
694 pub fn unpause_simulation(&self) {
697 match self {
698 WaveContainer::Wellen(_) => {}
699 WaveContainer::Empty => {}
700 WaveContainer::Cxxrtl(c) => c.lock().unwrap().unpause(),
701 }
702 }
703
704 pub fn pause_simulation(&self) {
706 match self {
707 WaveContainer::Wellen(_) => {}
708 WaveContainer::Empty => {}
709 WaveContainer::Cxxrtl(c) => c.lock().unwrap().pause(),
710 }
711 }
712
713 pub fn wellen_add_body(&mut self, body: BodyResult) -> Result<Option<LoadSignalsCmd>> {
715 match self {
716 WaveContainer::Wellen(inner) => inner.add_body(body),
717 _ => {
718 bail!("Should never call this function on a non wellen container!");
719 }
720 }
721 }
722
723 #[must_use]
724 pub fn body_loaded(&self) -> bool {
725 match self {
726 WaveContainer::Wellen(inner) => inner.body_loaded(),
727 WaveContainer::Empty => true,
728 WaveContainer::Cxxrtl(_) => true,
729 }
730 }
731
732 #[must_use]
735 pub fn supports_analog(&self) -> bool {
736 matches!(self, WaveContainer::Wellen(_))
737 }
738}
739
740#[cfg(test)]
741mod tests {
742 use super::*;
743
744 #[test]
745 fn extract_index_with_valid_index() {
746 let (name, index) = extract_index("signal[5]");
747 assert_eq!(name, "signal");
748 assert_eq!(index, Some(5));
749 }
750
751 #[test]
752 fn extract_index_with_zero_index() {
753 let (name, index) = extract_index("data[0]");
754 assert_eq!(name, "data");
755 assert_eq!(index, Some(0));
756 }
757
758 #[test]
759 fn extract_index_with_negative_index() {
760 let (name, index) = extract_index("array[-1]");
761 assert_eq!(name, "array");
762 assert_eq!(index, Some(-1));
763 }
764
765 #[test]
766 fn extract_index_with_large_number() {
767 let (name, index) = extract_index("mem[999999]");
768 assert_eq!(name, "mem");
769 assert_eq!(index, Some(999999));
770 }
771
772 #[test]
773 fn extract_index_no_brackets() {
774 let (name, index) = extract_index("simple_signal");
775 assert_eq!(name, "simple_signal");
776 assert_eq!(index, None);
777 }
778
779 #[test]
780 fn extract_index_empty_brackets() {
781 let (name, index) = extract_index("signal[]");
782 assert_eq!(name, "signal[]");
783 assert_eq!(index, None);
784 }
785
786 #[test]
787 fn extract_index_non_numeric_index() {
788 let (name, index) = extract_index("signal[abc]");
789 assert_eq!(name, "signal[abc]");
790 assert_eq!(index, None);
791 }
792
793 #[test]
794 fn extract_index_only_opening_bracket() {
795 let (name, index) = extract_index("signal[5");
796 assert_eq!(name, "signal[5");
797 assert_eq!(index, None);
798 }
799
800 #[test]
801 fn extract_index_only_closing_bracket() {
802 let (name, index) = extract_index("signal5]");
803 assert_eq!(name, "signal5]");
804 assert_eq!(index, None);
805 }
806
807 #[test]
808 fn extract_index_multiple_brackets() {
809 let (name, index) = extract_index("array[3][5]");
810 assert_eq!(name, "array[3]");
811 assert_eq!(index, Some(5));
812 }
813
814 #[test]
815 fn extract_index_with_dot_notation() {
816 let (name, index) = extract_index("struct.field[10]");
817 assert_eq!(name, "struct.field");
818 assert_eq!(index, Some(10));
819 }
820
821 #[test]
822 fn extract_index_bracket_at_start() {
823 let (name, index) = extract_index("[5]signal");
824 assert_eq!(name, "[5]signal");
825 assert_eq!(index, None);
826 }
827
828 #[test]
829 fn extract_index_no_text() {
830 let (name, index) = extract_index("[5]");
831 assert_eq!(name, "[5]");
832 assert_eq!(index, None);
833 }
834}