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