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