libsurfer/
variable_name_type.rs

1use derive_more::{Display, FromStr};
2use enum_iterator::Sequence;
3use itertools::Itertools;
4
5use serde::{Deserialize, Serialize};
6
7use crate::displayed_item_tree::Node;
8use crate::wave_container::{ScopeRefExt, VariableRefExt};
9use crate::{displayed_item::DisplayedItem, wave_container::VariableRef, wave_data::WaveData};
10
11#[derive(PartialEq, Copy, Clone, Debug, Deserialize, Display, FromStr, Serialize, Sequence)]
12pub enum VariableNameType {
13    /// Local variable name only (i.e. for tb.dut.clk => clk)
14    Local,
15
16    /// Add unique prefix, prefix + local
17    Unique,
18
19    /// Full variable name (i.e. tb.dut.clk => tb.dut.clk)
20    Global,
21}
22
23impl WaveData {
24    pub fn compute_variable_display_names(&mut self) {
25        let full_names = self
26            .items_tree
27            .iter()
28            .map(|node| self.displayed_items.get(&node.item_ref))
29            .filter_map(|item| match item {
30                Some(DisplayedItem::Variable(variable)) => Some(variable.variable_ref.clone()),
31                _ => None,
32            })
33            .unique()
34            .collect_vec();
35
36        for Node { item_ref, .. } in self.items_tree.iter() {
37            self.displayed_items
38                .entry(*item_ref)
39                .and_modify(|item| match item {
40                    DisplayedItem::Variable(variable) => {
41                        let local_name = variable.variable_ref.name.clone();
42                        variable.display_name = match variable.display_name_type {
43                            VariableNameType::Local => local_name,
44                            VariableNameType::Global => variable.variable_ref.full_path_string(),
45                            VariableNameType::Unique => {
46                                /// This function takes a full variable name and a list of other
47                                /// full variable names and returns a minimal unique variable name.
48                                /// It takes scopes from the back of the variable until the name is unique.
49                                fn unique(
50                                    variable: &VariableRef,
51                                    variables: &[VariableRef],
52                                ) -> String {
53                                    let other_variables = variables
54                                        .iter()
55                                        .filter(|&s| {
56                                            *s.full_path_string() != variable.full_path_string()
57                                        })
58                                        .collect_vec();
59
60                                    fn take_front(v: &VariableRef, l: usize) -> String {
61                                        if l == 0 {
62                                            v.name.clone()
63                                        } else {
64                                            format!(
65                                                "{}{}.{}",
66                                                if l < v.path.strs().len() { "…" } else { "" },
67                                                v.path.strs().iter().rev().take(l).rev().join("."),
68                                                v.name
69                                            )
70                                        }
71                                    }
72
73                                    let mut l = 0;
74                                    while other_variables
75                                        .iter()
76                                        .map(|v| take_front(v, l))
77                                        .contains(&take_front(variable, l))
78                                    {
79                                        l += 1;
80                                    }
81                                    take_front(variable, l)
82                                }
83
84                                unique(&variable.variable_ref, &full_names)
85                            }
86                        };
87                        if self.display_variable_indices {
88                            let index = self
89                                .inner
90                                .as_waves()
91                                .unwrap()
92                                .variable_meta(&variable.variable_ref)
93                                .ok()
94                                .as_ref()
95                                .and_then(|meta| meta.index)
96                                .map(|index| format!(" {index}"))
97                                .unwrap_or_default();
98                            variable.display_name = format!("{}{}", variable.display_name, index);
99                        }
100                    }
101                    DisplayedItem::Divider(_) => {}
102                    DisplayedItem::Marker(_) => {}
103                    DisplayedItem::TimeLine(_) => {}
104                    DisplayedItem::Placeholder(_) => {}
105                    DisplayedItem::Stream(_) => {}
106                    DisplayedItem::Group(_) => {}
107                });
108        }
109    }
110
111    pub fn force_variable_name_type(&mut self, name_type: VariableNameType) {
112        for Node { item_ref, .. } in self.items_tree.iter() {
113            self.displayed_items.entry(*item_ref).and_modify(|item| {
114                if let DisplayedItem::Variable(variable) = item {
115                    variable.display_name_type = name_type;
116                }
117            });
118        }
119        self.default_variable_name_type = name_type;
120        self.compute_variable_display_names();
121    }
122}