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 ZLib,
352 Lz4,
353 Lz4Duo,
354}
355
356type BitMaskWord = u64;
357
358pub(crate) struct BitMask {
359 inner: Vec<BitMaskWord>,
360}
361
362impl BitMask {
363 pub(crate) fn repeat(value: bool, size: usize) -> Self {
364 let word = if value { BitMaskWord::MAX } else { 0 };
365 let word_count = size.div_ceil(BitMaskWord::BITS as usize);
366 Self {
367 inner: vec![word; word_count],
368 }
369 }
370
371 pub(crate) fn set(&mut self, index: usize, value: bool) {
372 let (word_idx, bit_idx) = Self::word_and_bit_index(index);
373 if value {
374 self.inner[word_idx] |= (1 as BitMaskWord) << bit_idx;
375 } else {
376 self.inner[word_idx] &= !((1 as BitMaskWord) << bit_idx);
377 }
378 }
379
380 fn word_and_bit_index(index: usize) -> (usize, usize) {
381 let word_idx = index / BitMaskWord::BITS as usize;
382 let bit_idx = index - word_idx * BitMaskWord::BITS as usize;
383 (word_idx, bit_idx)
384 }
385
386 pub(crate) fn is_set(&self, index: usize) -> bool {
387 let (word_idx, bit_idx) = Self::word_and_bit_index(index);
388 (self.inner[word_idx] >> bit_idx) & 1 == 1
389 }
390}
391
392pub(crate) struct DataFilter {
393 pub(crate) start: u64,
394 pub(crate) end: u64,
395 pub(crate) signals: BitMask,
396}
397
398#[derive(Debug, Clone, Copy, PartialEq)]
399pub(crate) enum DataSectionKind {
400 Standard,
401 DynamicAlias,
402 DynamicAlias2,
403}
404
405#[derive(Debug, Clone, Copy)]
406pub(crate) enum ValueChangePackType {
407 Lz4,
408 FastLz,
409 Zlib,
410}
411
412impl ValueChangePackType {
413 pub(crate) fn from_u8(value: u8) -> Self {
414 match value {
415 b'4' => ValueChangePackType::Lz4,
416 b'F' => ValueChangePackType::FastLz,
417 _ => ValueChangePackType::Zlib,
418 }
419 }
420}
421
422impl DataSectionKind {
423 pub(crate) fn from_block_type(tpe: &BlockType) -> Option<Self> {
424 match tpe {
425 BlockType::VcData => Some(DataSectionKind::Standard),
426 BlockType::VcDataDynamicAlias => Some(DataSectionKind::DynamicAlias),
427 BlockType::VcDataDynamicAlias2 => Some(DataSectionKind::DynamicAlias2),
428 _ => None,
429 }
430 }
431}
432
433#[cfg(test)]
434mod tests {
435 use super::*;
436
437 #[test]
438 fn test_sizes() {
439 assert_eq!(std::mem::size_of::<SignalInfo>(), 4);
441 }
442}