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