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