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 AttributeBegin = 252,
107 AttributeEnd = 253,
108 VcdScope = 254,
110 VcdUpScope = 255,
111}
112
113#[repr(u8)]
114#[derive(Debug, TryFromPrimitive, PartialEq, Copy, Clone)]
115#[cfg_attr(test, derive(Arbitrary))]
116pub enum FstVarType {
117 Event = 0,
119 Integer = 1,
120 Parameter = 2,
121 Real = 3,
122 RealParameter = 4,
123 Reg = 5,
124 Supply0 = 6,
125 Supply1 = 7,
126 Time = 8,
127 Tri = 9,
128 TriAnd = 10,
129 TriOr = 11,
130 TriReg = 12,
131 Tri0 = 13,
132 Tri1 = 14,
133 Wand = 15, Wire = 16,
135 Wor = 17, Port = 18,
137 SparseArray = 19,
138 RealTime = 20,
139 GenericString = 21,
140 Bit = 22,
142 Logic = 23,
143 Int = 24,
144 ShortInt = 25,
145 LongInt = 26,
146 Byte = 27,
147 Enum = 28,
148 ShortReal = 29,
149}
150
151impl FstVarType {
152 pub fn is_real(&self) -> bool {
154 matches!(
155 self,
156 FstVarType::Real
157 | FstVarType::RealParameter
158 | FstVarType::RealTime
159 | FstVarType::ShortReal
160 )
161 }
162}
163
164#[repr(u8)]
165#[derive(Debug, TryFromPrimitive, Clone, Copy, PartialEq)]
166#[cfg_attr(test, derive(Arbitrary))]
167pub enum FstVarDirection {
168 Implicit = 0,
169 Input = 1,
170 Output = 2,
171 InOut = 3,
172 Buffer = 4,
173 Linkage = 5,
174}
175
176#[repr(u8)]
177#[derive(Debug, TryFromPrimitive, Clone, Copy, PartialEq)]
178#[cfg_attr(test, derive(Arbitrary))]
179pub enum FstVhdlVarType {
180 None = 0,
181 Signal = 1,
182 Variable = 2,
183 Constant = 3,
184 File = 4,
185 Memory = 5,
186}
187
188#[repr(u8)]
189#[derive(Debug, TryFromPrimitive, Clone, Copy, PartialEq)]
190#[cfg_attr(test, derive(Arbitrary))]
191pub enum FstVhdlDataType {
192 None = 0,
193 Boolean = 1,
194 Bit = 2,
195 Vector = 3,
196 ULogic = 4,
197 ULogicVector = 5,
198 Logic = 6,
199 LogicVector = 7,
200 Unsigned = 8,
201 Signed = 9,
202 Integer = 10,
203 Real = 11,
204 Natural = 12,
205 Positive = 13,
206 Time = 14,
207 Character = 15,
208 String = 16,
209}
210
211#[repr(u8)]
212#[derive(Debug, TryFromPrimitive, PartialEq)]
213pub enum AttributeType {
214 Misc = 0,
215 Array = 1,
216 Enum = 2,
217 Pack = 3,
218}
219
220#[repr(u8)]
221#[derive(Debug, TryFromPrimitive, PartialEq)]
222pub enum MiscType {
223 Comment = 0,
224 EnvVar = 1,
225 SupVar = 2,
226 PathName = 3,
227 SourceStem = 4,
228 SourceInstantiationStem = 5,
229 ValueList = 6,
230 EnumTable = 7,
231 Unknown = 8,
232}
233
234pub(crate) const DOUBLE_ENDIAN_TEST: f64 = std::f64::consts::E;
235
236#[derive(Debug, PartialEq)]
237#[cfg_attr(test, derive(Arbitrary))]
238#[allow(dead_code)]
239pub(crate) struct Header {
240 pub(crate) start_time: u64,
241 pub(crate) end_time: u64,
242 pub(crate) memory_used_by_writer: u64,
243 pub(crate) scope_count: u64,
244 pub(crate) var_count: u64,
245 pub(crate) max_var_id_code: u64, pub(crate) vc_section_count: u64,
247 pub(crate) timescale_exponent: i8,
248 pub(crate) version: String,
249 pub(crate) date: String,
250 pub(crate) file_type: FileType,
251 pub(crate) time_zero: u64,
252}
253
254#[derive(Debug, PartialEq)]
255#[cfg_attr(test, derive(Arbitrary))]
256pub(crate) enum SignalInfo {
257 BitVec(NonZeroU32),
258 Real,
259}
260
261impl SignalInfo {
262 pub(crate) fn from_file_format(value: u32) -> Self {
263 if value == 0 {
264 SignalInfo::Real
265 } else if value != u32::MAX {
266 SignalInfo::BitVec(NonZeroU32::new(value + 1).unwrap())
267 } else {
268 SignalInfo::BitVec(NonZeroU32::new(1).unwrap())
269 }
270 }
271
272 #[cfg(test)]
273 pub(crate) fn to_file_format(&self) -> u32 {
274 match self {
275 SignalInfo::BitVec(value) => match value.get() {
276 1 => u32::MAX,
277 other => other - 1,
278 },
279 SignalInfo::Real => 0,
280 }
281 }
282
283 #[inline]
284 pub(crate) fn len(&self) -> u32 {
285 match self {
286 SignalInfo::BitVec(value) => value.get() - 1,
287 SignalInfo::Real => 8,
288 }
289 }
290
291 #[inline]
292 pub(crate) fn is_real(&self) -> bool {
293 match self {
294 SignalInfo::BitVec(_) => false,
295 SignalInfo::Real => true,
296 }
297 }
298}
299
300#[derive(Debug, PartialEq)]
301#[cfg_attr(test, derive(Arbitrary))]
302pub(crate) struct BlackoutData {
303 pub(crate) time: u64,
304 pub(crate) contains_activity: bool,
305}
306
307#[derive(Debug, Clone)]
308pub(crate) struct DataSectionInfo {
309 pub(crate) file_offset: u64, pub(crate) start_time: u64,
311 pub(crate) end_time: u64,
312 pub(crate) kind: DataSectionKind,
313 #[allow(dead_code)]
315 pub(crate) mem_required_for_traversal: u64,
316}
317
318#[derive(Debug, PartialEq)]
319#[cfg_attr(test, derive(Arbitrary))]
320pub enum FstHierarchyEntry {
321 Scope {
322 tpe: FstScopeType,
323 name: String,
324 component: String,
325 },
326 UpScope,
327 Var {
328 tpe: FstVarType,
329 direction: FstVarDirection,
330 name: String,
331 length: u32,
332 handle: FstSignalHandle,
333 is_alias: bool,
334 },
335 PathName {
336 id: u64,
338 name: String,
339 },
340 SourceStem {
341 is_instantiation: bool,
342 path_id: u64,
343 line: u64,
344 },
345 Comment {
346 string: String,
347 },
348 EnumTable {
349 name: String,
350 handle: u64,
351 mapping: Vec<(String, String)>,
352 },
353 EnumTableRef {
354 handle: u64,
355 },
356 VhdlVarInfo {
357 type_name: String,
358 var_type: FstVhdlVarType,
359 data_type: FstVhdlDataType,
360 },
361 AttributeEnd,
362}
363
364#[derive(Debug, Copy, Clone)]
365#[cfg_attr(test, derive(Arbitrary))]
366pub(crate) enum HierarchyCompression {
367 Uncompressed,
368 ZLib,
369 Lz4,
370 Lz4Duo,
371}
372
373type BitMaskWord = u64;
374
375pub(crate) struct BitMask {
376 inner: Vec<BitMaskWord>,
377}
378
379impl BitMask {
380 pub(crate) fn repeat(value: bool, size: usize) -> Self {
381 let word = if value { BitMaskWord::MAX } else { 0 };
382 let word_count = size.div_ceil(BitMaskWord::BITS as usize);
383 Self {
384 inner: vec![word; word_count],
385 }
386 }
387
388 pub(crate) fn set(&mut self, index: usize, value: bool) {
389 let (word_idx, bit_idx) = Self::word_and_bit_index(index);
390 if value {
391 self.inner[word_idx] |= (1 as BitMaskWord) << bit_idx;
392 } else {
393 self.inner[word_idx] &= !((1 as BitMaskWord) << bit_idx);
394 }
395 }
396
397 fn word_and_bit_index(index: usize) -> (usize, usize) {
398 let word_idx = index / BitMaskWord::BITS as usize;
399 let bit_idx = index - word_idx * BitMaskWord::BITS as usize;
400 (word_idx, bit_idx)
401 }
402
403 pub(crate) fn is_set(&self, index: usize) -> bool {
404 let (word_idx, bit_idx) = Self::word_and_bit_index(index);
405 (self.inner[word_idx] >> bit_idx) & 1 == 1
406 }
407}
408
409pub(crate) struct DataFilter {
410 pub(crate) start: u64,
411 pub(crate) end: u64,
412 pub(crate) signals: BitMask,
413}
414
415#[derive(Debug, Clone, Copy, PartialEq)]
416pub(crate) enum DataSectionKind {
417 Standard,
418 DynamicAlias,
419 DynamicAlias2,
420}
421
422#[derive(Debug, Clone, Copy)]
423pub(crate) enum ValueChangePackType {
424 Lz4,
425 FastLz,
426 Zlib,
427}
428
429impl ValueChangePackType {
430 pub(crate) fn from_u8(value: u8) -> Self {
431 match value {
432 b'4' => ValueChangePackType::Lz4,
433 b'F' => ValueChangePackType::FastLz,
434 _ => ValueChangePackType::Zlib,
435 }
436 }
437}
438
439impl DataSectionKind {
440 pub(crate) fn from_block_type(tpe: &BlockType) -> Option<Self> {
441 match tpe {
442 BlockType::VcData => Some(DataSectionKind::Standard),
443 BlockType::VcDataDynamicAlias => Some(DataSectionKind::DynamicAlias),
444 BlockType::VcDataDynamicAlias2 => Some(DataSectionKind::DynamicAlias2),
445 _ => None,
446 }
447 }
448}
449
450#[cfg(test)]
451mod tests {
452 use super::*;
453
454 #[test]
455 fn test_sizes() {
456 assert_eq!(std::mem::size_of::<SignalInfo>(), 4);
458 }
459}