fst_native/
types.rs

1// Copyright 2023 The Regents of the University of California
2// released under BSD 3-Clause License
3// author: Kevin Laeufer <laeufer@berkeley.edu>
4// Contains FST in-memory types.
5
6use num_enum::TryFromPrimitive;
7#[cfg(test)]
8use proptest_derive::Arbitrary;
9use std::fmt::Formatter;
10use std::num::NonZeroU32;
11
12pub(crate) const HIERARCHY_NAME_MAX_SIZE: usize = 512;
13pub(crate) const HIERARCHY_ATTRIBUTE_MAX_SIZE: usize = 65536 + 4096;
14
15#[derive(Debug, PartialEq)]
16#[cfg_attr(test, derive(Arbitrary))]
17pub struct FstSignalHandle(NonZeroU32);
18
19impl FstSignalHandle {
20    pub(crate) fn new(value: u32) -> Self {
21        FstSignalHandle(NonZeroU32::new(value).unwrap())
22    }
23    pub fn from_index(index: usize) -> Self {
24        FstSignalHandle(NonZeroU32::new((index as u32) + 1).unwrap())
25    }
26    pub fn get_index(&self) -> usize {
27        (self.0.get() - 1) as usize
28    }
29    pub(crate) fn get_raw(&self) -> u32 {
30        self.0.get()
31    }
32}
33
34impl std::fmt::Display for FstSignalHandle {
35    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
36        write!(f, "H{}", self.0)
37    }
38}
39
40#[derive(Debug, PartialEq, Clone, Copy)]
41pub(crate) enum FloatingPointEndian {
42    Little,
43    Big,
44}
45
46#[repr(u8)]
47#[derive(Debug, TryFromPrimitive, Clone, Copy, PartialEq)]
48#[cfg_attr(test, derive(Arbitrary))]
49pub enum FileType {
50    Verilog = 0,
51    Vhdl = 1,
52    VerilogVhdl = 2,
53}
54
55#[repr(u8)]
56#[derive(Debug, TryFromPrimitive, PartialEq)]
57pub enum BlockType {
58    Header = 0,
59    VcData = 1,
60    Blackout = 2,
61    Geometry = 3,
62    Hierarchy = 4,
63    VcDataDynamicAlias = 5,
64    HierarchyLZ4 = 6,
65    HierarchyLZ4Duo = 7,
66    VcDataDynamicAlias2 = 8,
67    GZipWrapper = 254,
68    Skip = 255,
69}
70
71#[repr(u8)]
72#[derive(Debug, TryFromPrimitive, Clone, Copy, PartialEq)]
73#[cfg_attr(test, derive(Arbitrary))]
74pub enum FstScopeType {
75    // VCD
76    Module = 0,
77    Task = 1,
78    Function = 2,
79    Begin = 3,
80    Fork = 4,
81    Generate = 5,
82    Struct = 6,
83    Union = 7,
84    Class = 8,
85    Interface = 9,
86    Package = 10,
87    Program = 11,
88    // VHDL
89    VhdlArchitecture = 12,
90    VhdlProcedure = 13,
91    VhdlFunction = 14,
92    VhdlRecord = 15,
93    VhdlProcess = 16,
94    VhdlBlock = 17,
95    VhdlForGenerate = 18,
96    VhdlIfGenerate = 19,
97    VhdlGenerate = 20,
98    VhdlPackage = 21,
99    //
100    AttributeBegin = 252,
101    AttributeEnd = 253,
102    //
103    VcdScope = 254,
104    VcdUpScope = 255,
105}
106
107#[repr(u8)]
108#[derive(Debug, TryFromPrimitive, PartialEq, Copy, Clone)]
109#[cfg_attr(test, derive(Arbitrary))]
110pub enum FstVarType {
111    // VCD
112    Event = 0,
113    Integer = 1,
114    Parameter = 2,
115    Real = 3,
116    RealParameter = 4,
117    Reg = 5,
118    Supply0 = 6,
119    Supply1 = 7,
120    Time = 8,
121    Tri = 9,
122    TriAnd = 10,
123    TriOr = 11,
124    TriReg = 12,
125    Tri0 = 13,
126    Tri1 = 14,
127    Wand = 15, // or WAnd ?
128    Wire = 16,
129    Wor = 17, // or WOr?
130    Port = 18,
131    SparseArray = 19,
132    RealTime = 20,
133    GenericString = 21,
134    // System Verilog
135    Bit = 22,
136    Logic = 23,
137    Int = 24,
138    ShortInt = 25,
139    LongInt = 26,
140    Byte = 27,
141    Enum = 28,
142    ShortReal = 29,
143}
144
145#[repr(u8)]
146#[derive(Debug, TryFromPrimitive, Clone, Copy, PartialEq)]
147#[cfg_attr(test, derive(Arbitrary))]
148pub enum FstVarDirection {
149    Implicit = 0,
150    Input = 1,
151    Output = 2,
152    InOut = 3,
153    Buffer = 4,
154    Linkage = 5,
155}
156
157#[repr(u8)]
158#[derive(Debug, TryFromPrimitive, Clone, Copy, PartialEq)]
159#[cfg_attr(test, derive(Arbitrary))]
160pub enum FstVhdlVarType {
161    None = 0,
162    Signal = 1,
163    Variable = 2,
164    Constant = 3,
165    File = 4,
166    Memory = 5,
167}
168
169#[repr(u8)]
170#[derive(Debug, TryFromPrimitive, Clone, Copy, PartialEq)]
171#[cfg_attr(test, derive(Arbitrary))]
172pub enum FstVhdlDataType {
173    None = 0,
174    Boolean = 1,
175    Bit = 2,
176    Vector = 3,
177    ULogic = 4,
178    ULogicVector = 5,
179    Logic = 6,
180    LogicVector = 7,
181    Unsigned = 8,
182    Signed = 9,
183    Integer = 10,
184    Real = 11,
185    Natural = 12,
186    Positive = 13,
187    Time = 14,
188    Character = 15,
189    String = 16,
190}
191
192#[repr(u8)]
193#[derive(Debug, TryFromPrimitive, PartialEq)]
194pub enum AttributeType {
195    Misc = 0,
196    Array = 1,
197    Enum = 2,
198    Pack = 3,
199}
200
201#[repr(u8)]
202#[derive(Debug, TryFromPrimitive, PartialEq)]
203pub enum MiscType {
204    Comment = 0,
205    EnvVar = 1,
206    SupVar = 2,
207    PathName = 3,
208    SourceStem = 4,
209    SourceInstantiationStem = 5,
210    ValueList = 6,
211    EnumTable = 7,
212    Unknown = 8,
213}
214
215pub(crate) const DOUBLE_ENDIAN_TEST: f64 = std::f64::consts::E;
216
217#[derive(Debug, PartialEq)]
218#[cfg_attr(test, derive(Arbitrary))]
219#[allow(dead_code)]
220pub(crate) struct Header {
221    pub(crate) start_time: u64,
222    pub(crate) end_time: u64,
223    pub(crate) memory_used_by_writer: u64,
224    pub(crate) scope_count: u64,
225    pub(crate) var_count: u64,
226    pub(crate) max_var_id_code: u64, // aka maxhandle
227    pub(crate) vc_section_count: u64,
228    pub(crate) timescale_exponent: i8,
229    pub(crate) version: String,
230    pub(crate) date: String,
231    pub(crate) file_type: FileType,
232    pub(crate) time_zero: u64,
233}
234
235#[derive(Debug, PartialEq)]
236#[cfg_attr(test, derive(Arbitrary))]
237pub(crate) enum SignalInfo {
238    BitVec(NonZeroU32),
239    Real,
240}
241
242impl SignalInfo {
243    pub(crate) fn from_file_format(value: u32) -> Self {
244        if value == 0 {
245            SignalInfo::Real
246        } else if value != u32::MAX {
247            SignalInfo::BitVec(NonZeroU32::new(value + 1).unwrap())
248        } else {
249            SignalInfo::BitVec(NonZeroU32::new(1).unwrap())
250        }
251    }
252
253    pub(crate) fn to_file_format(&self) -> u32 {
254        match self {
255            SignalInfo::BitVec(value) => match value.get() {
256                1 => u32::MAX,
257                other => other - 1,
258            },
259            SignalInfo::Real => 0,
260        }
261    }
262
263    #[inline]
264    pub(crate) fn len(&self) -> u32 {
265        match self {
266            SignalInfo::BitVec(value) => value.get() - 1,
267            SignalInfo::Real => 8,
268        }
269    }
270
271    #[inline]
272    pub(crate) fn is_real(&self) -> bool {
273        match self {
274            SignalInfo::BitVec(_) => false,
275            SignalInfo::Real => true,
276        }
277    }
278}
279
280#[derive(Debug, PartialEq)]
281#[cfg_attr(test, derive(Arbitrary))]
282pub(crate) struct BlackoutData {
283    pub(crate) time: u64,
284    pub(crate) contains_activity: bool,
285}
286
287#[derive(Debug, Clone)]
288pub(crate) struct DataSectionInfo {
289    pub(crate) file_offset: u64, // points to section length
290    pub(crate) start_time: u64,
291    pub(crate) end_time: u64,
292    pub(crate) kind: DataSectionKind,
293}
294
295#[derive(Debug, PartialEq)]
296#[cfg_attr(test, derive(Arbitrary))]
297pub enum FstHierarchyEntry {
298    Scope {
299        tpe: FstScopeType,
300        name: String,
301        component: String,
302    },
303    UpScope,
304    Var {
305        tpe: FstVarType,
306        direction: FstVarDirection,
307        name: String,
308        length: u32,
309        handle: FstSignalHandle,
310        is_alias: bool,
311    },
312    PathName {
313        /// this id is used by other attributes to refer to the path
314        id: u64,
315        name: String,
316    },
317    SourceStem {
318        is_instantiation: bool,
319        path_id: u64,
320        line: u64,
321    },
322    Comment {
323        string: String,
324    },
325    EnumTable {
326        name: String,
327        handle: u64,
328        mapping: Vec<(String, String)>,
329    },
330    EnumTableRef {
331        handle: u64,
332    },
333    VhdlVarInfo {
334        type_name: String,
335        var_type: FstVhdlVarType,
336        data_type: FstVhdlDataType,
337    },
338    AttributeEnd,
339}
340
341#[derive(Debug, Copy, Clone)]
342#[cfg_attr(test, derive(Arbitrary))]
343pub(crate) enum HierarchyCompression {
344    ZLib,
345    Lz4,
346    Lz4Duo,
347}
348
349type BitMaskWord = u64;
350
351pub(crate) struct BitMask {
352    inner: Vec<BitMaskWord>,
353}
354
355impl BitMask {
356    pub(crate) fn repeat(value: bool, size: usize) -> Self {
357        let word = if value { BitMaskWord::MAX } else { 0 };
358        let word_count = size.div_ceil(BitMaskWord::BITS as usize);
359        Self {
360            inner: vec![word; word_count],
361        }
362    }
363
364    pub(crate) fn set(&mut self, index: usize, value: bool) {
365        let (word_idx, bit_idx) = Self::word_and_bit_index(index);
366        if value {
367            self.inner[word_idx] |= (1 as BitMaskWord) << bit_idx;
368        } else {
369            self.inner[word_idx] &= !((1 as BitMaskWord) << bit_idx);
370        }
371    }
372
373    fn word_and_bit_index(index: usize) -> (usize, usize) {
374        let word_idx = index / BitMaskWord::BITS as usize;
375        let bit_idx = index - word_idx * BitMaskWord::BITS as usize;
376        (word_idx, bit_idx)
377    }
378
379    pub(crate) fn is_set(&self, index: usize) -> bool {
380        let (word_idx, bit_idx) = Self::word_and_bit_index(index);
381        (self.inner[word_idx] >> bit_idx) & 1 == 1
382    }
383}
384
385pub(crate) struct DataFilter {
386    pub(crate) start: u64,
387    pub(crate) end: u64,
388    pub(crate) signals: BitMask,
389}
390
391#[derive(Debug, Clone, Copy, PartialEq)]
392pub(crate) enum DataSectionKind {
393    Standard,
394    DynamicAlias,
395    DynamicAlias2,
396}
397
398#[derive(Debug, Clone, Copy)]
399pub(crate) enum ValueChangePackType {
400    Lz4,
401    FastLz,
402    Zlib,
403}
404
405impl ValueChangePackType {
406    pub(crate) fn from_u8(value: u8) -> Self {
407        match value {
408            b'4' => ValueChangePackType::Lz4,
409            b'F' => ValueChangePackType::FastLz,
410            _ => ValueChangePackType::Zlib,
411        }
412    }
413}
414
415impl DataSectionKind {
416    pub(crate) fn from_block_type(tpe: &BlockType) -> Option<Self> {
417        match tpe {
418            BlockType::VcData => Some(DataSectionKind::Standard),
419            BlockType::VcDataDynamicAlias => Some(DataSectionKind::DynamicAlias),
420            BlockType::VcDataDynamicAlias2 => Some(DataSectionKind::DynamicAlias2),
421            _ => None,
422        }
423    }
424}
425
426#[cfg(test)]
427mod tests {
428    use super::*;
429
430    #[test]
431    fn test_sizes() {
432        // 1-bit to distinguish between real and bitvec + length
433        assert_eq!(std::mem::size_of::<SignalInfo>(), 4);
434    }
435}