vcd_io/
lib.rs

1#![allow(dead_code)]
2// const VCD_KEYWORDS: [&str;12] =
3// 			["$commet","$date","$end","$timescale","$var",
4// 			"$upscope","$enddefinitions","$dumpvars","$version","$dumpall",
5// 			"$scope","dumpoff","dumpon"];
6use serde::{Serialize, Deserialize};
7
8mod error;
9mod parser;
10mod saver;
11
12use parser::vcd_parser;
13
14use crate::error::VcdError;
15
16#[derive(PartialEq, Debug, Copy, Clone,Serialize, Deserialize,Default)]
17pub enum TimeUnit {
18    Psec,
19    #[default]
20    Nsec,
21    Usec,
22    Msec,
23    Sec,
24}
25
26use std::fmt::{self, Display};
27
28impl Display for TimeUnit {
29    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30        match &self {
31            TimeUnit::Psec => write!(f, "ps"),
32            TimeUnit::Nsec => write!(f, "ns"),
33            TimeUnit::Usec => write!(f, "us"),
34            TimeUnit::Msec => write!(f, "ms"),
35            TimeUnit::Sec => write!(f, "s"),
36        }
37    }
38}
39
40#[derive(PartialEq, Debug, Copy, Clone,Serialize, Deserialize)]
41pub enum VarType {
42    Wire,
43    Reg,
44    TriReg,
45    Integer,
46    Port,
47}
48
49impl TryFrom<u8> for VarType {
50    type Error = &'static str;
51
52    fn try_from(data: u8) -> Result<Self, Self::Error> {
53        match data {
54            0 => Ok(VarType::Wire),
55            1 => Ok(VarType::Reg),
56            2 => Ok(VarType::TriReg),
57            3 => Ok(VarType::Integer),
58            4 => Ok(VarType::Port),
59            _ => Err("bad encoded variable type"),
60        }
61    }
62}
63
64impl From<VarType> for u8 {
65    fn from(data: VarType) -> Self {
66        let exp: u8 = match data {
67            VarType::Wire => 0,
68            VarType::Reg => 1,
69            VarType::TriReg => 2,
70            VarType::Integer => 3,
71            VarType::Port => 4,
72        };
73        exp
74    }
75}
76
77impl Display for VarType {
78    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79        match &self {
80            VarType::Wire => write!(f, "wire"),
81            VarType::Reg => write!(f, "reg"),
82            VarType::TriReg => write!(f, "trireg"),
83            VarType::Integer => write!(f, "integer"),
84            VarType::Port => write!(f, "port"),
85        }
86    }
87}
88
89#[derive(PartialEq, Debug, Copy, Clone,Serialize,Deserialize)]
90pub enum ScopeType {
91    Module,
92    Task,
93    Function,
94    Fork,
95}
96
97impl TryFrom<u8> for ScopeType {
98    type Error = &'static str;
99
100    fn try_from(data: u8) -> Result<Self, Self::Error> {
101        match data {
102            0 => Ok(ScopeType::Module),
103            1 => Ok(ScopeType::Task),
104            2 => Ok(ScopeType::Function),
105            3 => Ok(ScopeType::Fork),
106            _ => Err("bad encoded variable type"),
107        }
108    }
109}
110
111impl From<ScopeType> for u8 {
112    fn from(data: ScopeType) -> Self {
113        let exp: u8 = match data {
114            ScopeType::Module => 0,
115            ScopeType::Task => 1,
116            ScopeType::Function => 2,
117            ScopeType::Fork => 3,
118        };
119        exp
120    }
121}
122
123impl Display for ScopeType {
124    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125        match &self {
126            ScopeType::Module => write!(f, "module"),
127            ScopeType::Task => write!(f, "task"),
128            ScopeType::Function => write!(f, "function"),
129            ScopeType::Fork => write!(f, "fork"),
130        }
131    }
132}
133
134#[derive(PartialEq, Debug, Clone, Copy)]
135pub enum ScalarValue {
136    ZeroOne(bool),
137    Xstate,
138    Zstate,
139}
140
141#[cfg(feature = "dev")]
142use rand::{
143    distributions::{Distribution, Standard},
144    Rng,
145};
146
147#[cfg(feature = "dev")]
148impl Distribution<ScalarValue> for Standard {
149    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> ScalarValue {
150        match rng.gen_range(0..=3) {
151            0 => ScalarValue::ZeroOne(true),
152            1 => ScalarValue::ZeroOne(false),
153            2 => ScalarValue::Xstate,
154            3 => ScalarValue::Zstate,
155            _ => ScalarValue::ZeroOne(false),
156        }
157    }
158}
159
160#[cfg(feature = "dev")]
161impl Distribution<VarType> for Standard {
162    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> VarType {
163        match rng.gen_range(0..=3) {
164            0 => VarType::Port,
165            1 => VarType::Reg,
166            2 => VarType::TriReg,
167            3 => VarType::Integer,
168            _ => VarType::Wire,
169        }
170    }
171
172    // other methods in Distribution are derived from `sample`
173}
174
175
176impl Display for ScalarValue {
177    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
178        match &self {
179            ScalarValue::ZeroOne(v) => match &v {
180                true => write!(f, "1"),
181                false => write!(f, "0"),
182            },
183            ScalarValue::Xstate => write!(f, "x"),
184            ScalarValue::Zstate => write!(f, "z"),
185        }
186    }
187}
188
189impl Default for ScalarValue {
190    fn default() -> Self {
191        ScalarValue::Xstate
192    }
193}
194
195impl std::ops::Not for ScalarValue {
196    type Output = Self;
197
198    fn not(self) -> Self::Output {
199        match self {
200            ScalarValue::ZeroOne(b) => ScalarValue::ZeroOne(!b),
201            ScalarValue::Xstate => ScalarValue::Xstate,
202            ScalarValue::Zstate => ScalarValue::Zstate,
203        }
204    }
205}
206
207impl std::ops::BitXor for ScalarValue {
208    type Output = Self;
209
210    fn bitxor(self, rhs: Self) -> Self::Output {
211        match (self, rhs) {
212            (ScalarValue::ZeroOne(s1), ScalarValue::ZeroOne(s2)) => ScalarValue::ZeroOne(s1 ^ s2),
213            (ScalarValue::Xstate, _)
214            | (ScalarValue::Zstate, _)
215            | (_, ScalarValue::Xstate)
216            | (_, ScalarValue::Zstate) => ScalarValue::ZeroOne(false),
217        }
218    }
219}
220
221#[derive(PartialEq, Debug, Clone)]
222pub enum VarValue {
223    Scalar(ScalarValue),
224    Vector(Vec<ScalarValue>),
225    Real(String), // as we dont know real value type, can be converted later
226}
227impl VarValue {
228    pub fn padding(&mut self,target_width:usize) -> bool {
229        if let VarValue::Vector(ref mut vec) = self {
230            if target_width < vec.len() {
231                return false;
232            }
233            let remain_bits = target_width - vec.len();
234            if vec.len() == 1 {
235                if vec[0] != ScalarValue::ZeroOne(true) {
236                    (0..remain_bits).into_iter().for_each(|_|vec.push(vec[0]));
237                } else {
238                    (0..remain_bits).into_iter().for_each(|_|vec.push(ScalarValue::ZeroOne(false)));
239                }
240            } else {
241                (0..remain_bits).into_iter().for_each(|_|vec.push(ScalarValue::ZeroOne(false)));
242            }
243        }
244        true
245    }
246}
247
248impl Display for VarValue {
249    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
250        match &self {
251            VarValue::Scalar(s) => write!(f, "{}", s),
252            VarValue::Vector(v) => {
253                write!(f, "b")?;
254                for a_v in v {
255                    write!(f, "{}", a_v)?;
256                }
257                Ok(())
258            }
259            VarValue::Real(r) => write!(f, "r{}", r),
260        }
261    }
262}
263
264#[derive(PartialEq, Debug, Clone,Serialize, Deserialize)]
265pub struct Variable {
266    pub var_type: VarType,
267    pub name: String,
268    pub width: u16,
269}
270
271#[derive(PartialEq, Debug, Clone)]
272pub struct Scope {
273    pub scope_type: ScopeType,
274    pub scope_name: String,
275    pub sub_scope_idx: Vec<ScopeIndex>,
276    pub variables: Vec<VariableIndex>,
277}
278
279use std::collections::HashMap;
280
281use nom::{error::VerboseError, IResult};
282
283pub type ScopeIndex = usize;
284pub type VariableIndex = usize;
285pub type ValueIndex = usize;
286
287pub type VcdRes<T, U> = IResult<T, U, VerboseError<T>>;
288
289pub struct VcdDb {
290    // VCD header
291    pub date: String,
292    pub version: String,
293    pub comment: String,
294    pub timescale: (u32, TimeUnit),
295
296    // list of timestap
297    pub timestap: Vec<u32>,
298    // list of scope
299    pub scope: Vec<Scope>,
300    // list of variable
301    pub variable: Vec<Variable>,
302    // 1st dimension is timestamp, 2nd dimension is signal
303    pub var_value: Vec<Vec<VarValue>>,
304    // <variable identifier, variable index> mapping
305    pub var_id_map: HashMap<String, VariableIndex>,
306    // <variable identifier, value index> mapping
307    // pub var_value_map:HashMap<String,ValueIndex>,
308    // <value index,variable identifier> mapping
309    pub value_var_map: HashMap<ValueIndex, String>,
310    // indicate start index of value, because vcd may missing value if no transition happened after a timestamp
311    pub padding_value: Vec<Vec<usize>>,
312}
313
314impl VcdDb {
315    pub fn new() -> Self {
316        VcdDb::default()
317    }
318
319    pub fn aligned(&self) -> bool {
320        let var_num = self.variable.len();
321        for val in &self.var_value {
322            if val.len() != var_num {
323                return false;
324            }
325        }
326        return true;
327    }
328
329    // result: 
330    // 1. clean data in padding value and align data in var_value
331    // 2. clean data in value_var_map
332    pub fn align_var_value(&mut self) -> bool {
333        let var_num = self.variable.len();
334        let mut prev_cycle_data = self.var_value[0].clone();
335        let mut curr_cycle_data = prev_cycle_data.clone();
336        println!("total var num {:?}", curr_cycle_data.len());
337        let mut mask:Vec<bool> = std::iter::repeat(false).take(var_num).collect();
338        let mut internal_cursor = 0;
339
340        for (i,padding) in self.padding_value[1..].iter().enumerate() {
341            if padding.len() + self.var_value[i+1].len() != var_num {
342                // broken data
343                return false;
344            }
345            for p in padding {
346                mask[*p] = true;
347            }
348            mask.iter().enumerate().for_each(|(j,is_masked)|{
349                if *is_masked {
350                    curr_cycle_data[j] = prev_cycle_data[j].clone();
351                } else {
352                    curr_cycle_data[j] = self.var_value[i+1][internal_cursor].clone();
353                    internal_cursor += 1;
354                }
355            });
356
357            self.var_value[i+1] = curr_cycle_data.clone();
358            prev_cycle_data = curr_cycle_data.clone();
359            internal_cursor = 0;
360        }
361
362        self.padding_value.clear();
363        true
364    }
365
366
367}
368
369impl Default for VcdDb {
370    fn default() -> Self {
371        VcdDb {
372            timescale: (1, TimeUnit::Psec),
373            date: String::from(""),
374            version: String::from(""),
375            comment: String::from(""),
376            timestap: vec![],
377            scope: vec![],
378            variable: vec![],
379            var_value: vec![],
380            var_id_map: HashMap::new(),
381            value_var_map: HashMap::new(),
382            padding_value: vec![],
383        }
384    }
385}
386
387pub fn multi_parse_vcd(file: &str) -> Result<VcdDb, VcdError> {
388    let (s, r) = std::sync::mpsc::channel();
389    s.send(std::fs::read_to_string(&file).unwrap()).unwrap();
390
391    let vcd: VcdDb = vcd_parser(&r.recv().unwrap())?;
392    Ok(vcd)
393}
394
395pub fn parse_vcd(file: &str) -> Result<VcdDb, VcdError> {
396    // let report = VcdIoReport::new(&file);
397    // let buff = std::fs::read_to_string(&file)?;
398    let vcd: VcdDb = vcd_parser(file)?;
399    Ok(vcd)
400}