surfer_translation_types/
lib.rs

1mod field_ref;
2pub mod plugin_types;
3#[cfg(feature = "pyo3")]
4pub mod python;
5mod result;
6mod scope_ref;
7pub mod translator;
8pub mod variable_index;
9mod variable_ref;
10
11use derive_more::Display;
12use ecolor::Color32;
13#[cfg(feature = "wasm_plugins")]
14use extism_convert::{FromBytes, Json, ToBytes};
15use num::BigUint;
16use serde::{Deserialize, Serialize};
17use std::collections::HashMap;
18
19pub use crate::field_ref::FieldRef;
20pub use crate::result::{
21    HierFormatResult, SubFieldFlatTranslationResult, SubFieldTranslationResult, TranslatedValue,
22    TranslationResult, ValueRepr,
23};
24pub use crate::scope_ref::ScopeRef;
25pub use crate::translator::{
26    translates_all_bit_types, BasicTranslator, Translator, VariableNameInfo, WaveSource,
27};
28pub use crate::variable_index::VariableIndex;
29pub use crate::variable_ref::VariableRef;
30
31#[cfg_attr(feature = "wasm_plugins", derive(FromBytes, ToBytes))]
32#[cfg_attr(feature = "wasm_plugins", encoding(Json))]
33#[derive(Deserialize, Serialize)]
34pub struct PluginConfig(pub HashMap<String, String>);
35
36/// Turn vector variable string into name and corresponding color if it
37/// includes values other than 0 and 1. If only 0 and 1, return None.
38pub fn check_vector_variable(s: &str) -> Option<(String, ValueKind)> {
39    if s.contains('x') {
40        Some(("UNDEF".to_string(), ValueKind::Undef))
41    } else if s.contains('z') {
42        Some(("HIGHIMP".to_string(), ValueKind::HighImp))
43    } else if s.contains('-') {
44        Some(("DON'T CARE".to_string(), ValueKind::DontCare))
45    } else if s.contains('u') {
46        Some(("UNDEF".to_string(), ValueKind::Undef))
47    } else if s.contains('w') {
48        Some(("UNDEF WEAK".to_string(), ValueKind::Undef))
49    } else if s.contains('h') || s.contains('l') {
50        Some(("WEAK".to_string(), ValueKind::Weak))
51    } else if s.chars().all(|c| c == '0' || c == '1') {
52        None
53    } else {
54        Some(("UNKNOWN VALUES".to_string(), ValueKind::Undef))
55    }
56}
57
58/// VCD bit extension
59pub fn extend_string(val: &str, num_bits: u64) -> String {
60    if num_bits > val.len() as u64 {
61        let extra_count = num_bits - val.len() as u64;
62        let extra_value = match val.chars().next() {
63            Some('0') => "0",
64            Some('1') => "0",
65            Some('x') => "x",
66            Some('z') => "z",
67            // If we got weird characters, this is probably a string, so we don't
68            // do the extension
69            // We may have to add extensions for std_logic values though if simulators save without extension
70            _ => "",
71        };
72        extra_value.repeat(extra_count as usize)
73    } else {
74        String::new()
75    }
76}
77
78#[derive(Debug, PartialEq, Clone, Display, Serialize, Deserialize)]
79pub enum VariableValue {
80    #[display("{_0}")]
81    BigUint(BigUint),
82    #[display("{_0}")]
83    String(String),
84}
85
86impl VariableValue {
87    /// Utility function for handling the happy case of the variable value being only 0 and 1,
88    /// with default handling of other values.
89    ///
90    /// The value passed to the handler is guaranteed to only contain 0 and 1, but it is not
91    /// padded to the length of the vector, i.e. leading zeros can be missing. Use [extend_string]
92    /// on the result to add the padding.
93    pub fn handle_bits<E>(
94        self,
95        handler: impl Fn(String) -> Result<TranslationResult, E>,
96    ) -> Result<TranslationResult, E> {
97        let value = match self {
98            VariableValue::BigUint(v) => format!("{v:b}"),
99            VariableValue::String(v) => {
100                if let Some((val, kind)) = check_vector_variable(&v) {
101                    return Ok(TranslationResult {
102                        val: ValueRepr::String(val),
103                        subfields: vec![],
104                        kind,
105                    });
106                } else {
107                    v
108                }
109            }
110        };
111
112        handler(value)
113    }
114}
115
116#[derive(Clone, PartialEq, Copy, Debug, Serialize, Deserialize)]
117pub enum ValueKind {
118    Normal,
119    Undef,
120    HighImp,
121    Custom(Color32),
122    Warn,
123    DontCare,
124    Weak,
125}
126
127#[cfg_attr(feature = "wasm_plugins", derive(FromBytes, ToBytes))]
128#[cfg_attr(feature = "wasm_plugins", encoding(Json))]
129#[derive(PartialEq, Deserialize, Serialize)]
130pub enum TranslationPreference {
131    /// This translator prefers translating the variable, so it will be selected
132    /// as the default translator for the variable
133    Prefer,
134    /// This translator is able to translate the variable, but will not be
135    /// selected by default, the user has to select it
136    Yes,
137    No,
138}
139
140/// Static information about the structure of a variable.
141#[cfg_attr(feature = "wasm_plugins", derive(FromBytes, ToBytes))]
142#[cfg_attr(feature = "wasm_plugins", encoding(Json))]
143#[derive(Clone, Debug, Default, Deserialize, Serialize)]
144pub enum VariableInfo {
145    Compound {
146        subfields: Vec<(String, VariableInfo)>,
147    },
148    Bits,
149    Bool,
150    Clock,
151    // NOTE: only used for state saving where translators will clear this out with the actual value
152    #[default]
153    String,
154    Real,
155}
156
157#[derive(Debug, Display, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
158pub enum VariableType {
159    // VCD-specific types
160    #[display("event")]
161    VCDEvent,
162    #[display("reg")]
163    VCDReg,
164    #[display("wire")]
165    VCDWire,
166    #[display("real")]
167    VCDReal,
168    #[display("time")]
169    VCDTime,
170    #[display("string")]
171    VCDString,
172    #[display("parameter")]
173    VCDParameter,
174    #[display("integer")]
175    VCDInteger,
176    #[display("real time")]
177    VCDRealTime,
178    #[display("supply 0")]
179    VCDSupply0,
180    #[display("supply 1")]
181    VCDSupply1,
182    #[display("tri")]
183    VCDTri,
184    #[display("tri and")]
185    VCDTriAnd,
186    #[display("tri or")]
187    VCDTriOr,
188    #[display("tri reg")]
189    VCDTriReg,
190    #[display("tri 0")]
191    VCDTri0,
192    #[display("tri 1")]
193    VCDTri1,
194    #[display("wand")]
195    VCDWAnd,
196    #[display("wor")]
197    VCDWOr,
198    #[display("port")]
199    Port,
200    #[display("sparse array")]
201    SparseArray,
202    #[display("realtime")]
203    RealTime,
204
205    // System Verilog
206    #[display("bit")]
207    Bit,
208    #[display("logic")]
209    Logic,
210    #[display("int")]
211    Int,
212    #[display("shortint")]
213    ShortInt,
214    #[display("longint")]
215    LongInt,
216    #[display("byte")]
217    Byte,
218    #[display("enum")]
219    Enum,
220    #[display("shortreal")]
221    ShortReal,
222
223    // VHDL (these are the types emitted by GHDL)
224    #[display("boolean")]
225    Boolean,
226    #[display("bit_vector")]
227    BitVector,
228    #[display("std_logic")]
229    StdLogic,
230    #[display("std_logic_vector")]
231    StdLogicVector,
232    #[display("std_ulogic")]
233    StdULogic,
234    #[display("std_ulogic_vector")]
235    StdULogicVector,
236}
237
238#[derive(Clone, Display, Copy, PartialOrd, Debug, Eq, PartialEq, Serialize, Deserialize)]
239pub enum VariableDirection {
240    // Ordering is used for sorting variable list
241    #[display("input")]
242    Input,
243    #[display("output")]
244    Output,
245    #[display("inout")]
246    InOut,
247    #[display("buffer")]
248    Buffer,
249    #[display("linkage")]
250    Linkage,
251    #[display("implicit")]
252    Implicit,
253    #[display("unknown")]
254    Unknown,
255}
256
257#[cfg_attr(feature = "wasm_plugins", derive(FromBytes, ToBytes))]
258#[cfg_attr(feature = "wasm_plugins", encoding(Json))]
259#[derive(Clone, Debug, Serialize, Deserialize)]
260pub struct VariableMeta<VarId, ScopeId> {
261    pub var: VariableRef<VarId, ScopeId>,
262    pub num_bits: Option<u32>,
263    /// Type of the variable in the HDL (on a best effort basis).
264    pub variable_type: Option<VariableType>,
265    /// Type name of variable, if available
266    pub variable_type_name: Option<String>,
267    pub index: Option<VariableIndex>,
268    pub direction: Option<VariableDirection>,
269    pub enum_map: HashMap<String, String>,
270    /// Indicates how the variable is stored. A variable of "type" boolean for example
271    /// could be stored as a String or as a BitVector.
272    pub encoding: VariableEncoding,
273}
274
275#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
276pub enum VariableEncoding {
277    String,
278    Real,
279    BitVector,
280}
281
282impl<VarId1, ScopeId1> VariableMeta<VarId1, ScopeId1> {
283    pub fn map_ids<VarId2, ScopeId2>(
284        self,
285        var_fn: impl FnMut(VarId1) -> VarId2,
286        scope_fn: impl FnMut(ScopeId1) -> ScopeId2,
287    ) -> VariableMeta<VarId2, ScopeId2> {
288        VariableMeta {
289            var: self.var.map_ids(var_fn, scope_fn),
290            num_bits: self.num_bits,
291            variable_type: self.variable_type,
292            index: self.index,
293            direction: self.direction,
294            enum_map: self.enum_map,
295            encoding: self.encoding,
296            variable_type_name: self.variable_type_name,
297        }
298    }
299}