From c0d245c0e5445ed20d9b9eb4e224cef61102a7af Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Wed, 6 Sep 2023 12:53:38 +0200 Subject: [PATCH 1/5] Update README with more information about surfer --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 105415f..18f1415 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ Copyright - Yehowshua Immanuel # Status -July 25 2022: Haven't worked on this in a while. It seems the Zoq is now pushing forward on this codebase. -Check out his frontend here: https://gitlab.com/TheZoq2/surfer +July 25 2023: Haven't worked on this in a while. It seems the Zoq is now pushing forward on this codebase. +Check out his frontend here: https://app.surfer-project.org/ (code at https://gitlab.com/surfer-proj/surfer ) # A High performance, VCD Parser written in Rust -- 2.47.1 From 73332179ee387bdb341f4d9f0ba6d71d8bb10709 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Wed, 6 Sep 2023 13:02:02 +0200 Subject: [PATCH 2/5] Replace deprecated method --- src/vcd/parse/metadata.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vcd/parse/metadata.rs b/src/vcd/parse/metadata.rs index b908403..126a334 100644 --- a/src/vcd/parse/metadata.rs +++ b/src/vcd/parse/metadata.rs @@ -2,7 +2,7 @@ // This program is distributed under both the GPLV3 license // and the YEHOWSHUA license, both of which can be found at // the root of the folder containing the sources for this program. -use chrono::prelude::{DateTime, Utc, TimeZone}; +use chrono::prelude::{DateTime, Utc}; use itertools::Itertools; use super::super::reader::{Cursor, WordReader, next_word}; @@ -133,9 +133,9 @@ pub(super) fn parse_date( // unfortunately, the minutes, seconds, and hour could occur in an // unexpected order let full_date = format!("{day} {month} {date} {hh}:{mm}:{ss} {year}"); - let full_date = Utc.datetime_from_str(full_date.as_str(), "%a %b %e %T %Y"); + let full_date = DateTime::parse_from_str(full_date.as_str(), "%a %b %e %T %Y"); if full_date.is_ok() { - return Ok(full_date.unwrap()); + return Ok(full_date.unwrap().into()); } Err(format!( -- 2.47.1 From f2689885bed023acc9b617e8957b2709b4f95a1b Mon Sep 17 00:00:00 2001 From: Lucas Klemmer Date: Sun, 10 Sep 2023 16:23:04 +0200 Subject: [PATCH 3/5] Add real_idx function to signal --- src/vcd/signal.rs | 103 ++++++++++++++++++++++++---------------------- 1 file changed, 53 insertions(+), 50 deletions(-) diff --git a/src/vcd/signal.rs b/src/vcd/signal.rs index 0ac29ef..f9c6103 100644 --- a/src/vcd/signal.rs +++ b/src/vcd/signal.rs @@ -2,8 +2,8 @@ // This program is distributed under both the GPLV3 license // and the YEHOWSHUA license, both of which can be found at // the root of the folder containing the sources for this program. -use super::types::SignalIdx; use super::types; +use super::types::SignalIdx; use num::BigUint; // Index to the least significant byte of a timestamp @@ -39,11 +39,18 @@ impl<'a> Signal<'a> { pub fn path(&self) -> &[String] { match self.0 { - SignalEnum::Data {path, ..} => path, + SignalEnum::Data { path, .. } => path, SignalEnum::Alias { path, .. } => path, } } + pub fn real_idx(&self) -> SignalIdx { + match self.0 { + SignalEnum::Data { self_idx, .. } => *self_idx, + SignalEnum::Alias { signal_alias, .. } => *signal_alias, + } + } + pub fn num_bits(&self) -> Option { let Signal(signal_enum) = &self; signal_enum.bits_required() @@ -55,7 +62,9 @@ impl<'a> Signal<'a> { vcd: &types::VCD, ) -> Result { let Signal(signal_enum) = &self; - signal_enum.query_string_val_on_tmln(desired_time, &vcd.tmstmps_encoded_as_u8s, &vcd.all_signals).map(|(val, _)| val) + signal_enum + .query_string_val_on_tmln(desired_time, &vcd.tmstmps_encoded_as_u8s, &vcd.all_signals) + .map(|(val, _)| val) } pub fn query_num_val_on_tmln( &self, @@ -63,7 +72,9 @@ impl<'a> Signal<'a> { vcd: &types::VCD, ) -> Result { let Signal(signal_enum) = &self; - signal_enum.query_num_val_on_tmln(desired_time, &vcd.tmstmps_encoded_as_u8s, &vcd.all_signals).map(|(val, _)| val) + signal_enum + .query_num_val_on_tmln(desired_time, &vcd.tmstmps_encoded_as_u8s, &vcd.all_signals) + .map(|(val, _)| val) } pub fn query_val_on_tmln( @@ -72,18 +83,16 @@ impl<'a> Signal<'a> { vcd: &types::VCD, ) -> Result<(TimeStamp, SignalValue), SignalErrors> { let Signal(signal_enum) = &self; - let num_val = signal_enum - .query_num_val_on_tmln( - desired_time, - &vcd.tmstmps_encoded_as_u8s, - &vcd.all_signals - ); - let str_val = signal_enum - .query_string_val_on_tmln( - desired_time, - &vcd.tmstmps_encoded_as_u8s, - &vcd.all_signals - ); + let num_val = signal_enum.query_num_val_on_tmln( + desired_time, + &vcd.tmstmps_encoded_as_u8s, + &vcd.all_signals, + ); + let str_val = signal_enum.query_string_val_on_tmln( + desired_time, + &vcd.tmstmps_encoded_as_u8s, + &vcd.all_signals, + ); // Both num and str will return the newest value that is closest to // the desired time. If both have valid values, select the most recent @@ -92,14 +101,13 @@ impl<'a> Signal<'a> { (Ok((num_val, num_time)), Ok((str_val, str_time))) => { if num_time > str_time { Ok((num_time, SignalValue::BigUint(num_val))) - } - else { + } else { Ok((str_time, SignalValue::String(str_val))) } } (Ok((num_val, time)), Err(_)) => Ok((time, SignalValue::BigUint(num_val))), (Err(_), Ok((str_val, time))) => Ok((time, SignalValue::String(str_val))), - (Err(e), _e) => Err(e) + (Err(e), _e) => Err(e), } } } @@ -122,23 +130,23 @@ pub(super) enum SignalEnum { /// A signal may take on a new value and hold that value /// for sometime. We only need to record the value of a signal /// when it changes(the is what VCDs tend to do). - /// A signal may need x amount of bytes to record its largest - /// possible value, so we record every single value of a given + /// A signal may need x amount of bytes to record its largest + /// possible value, so we record every single value of a given /// signal as a sequence of x number of u8s. /// For example, we might find that `my_signal. /// nums_encoded_as_fixed_width_le_u8` /// has two 32 bit values, namely, 1 and 2, encoded as follows: - /// my_signal.nums_encoded_as_fixed_width_le_u8 = vec![1u8, 0u8, + /// my_signal.nums_encoded_as_fixed_width_le_u8 = vec![1u8, 0u8, /// 0u8, 0u8, 2u8, 0u8, 0u8, 0u8]; nums_encoded_as_fixed_width_le_u8: Vec, string_vals: Vec, - /// we could do Vec<(LsbIdxOfTmstmpValOnTmln, u8)>, but I - /// suspect that Vec is more cache - /// friendly. We use ``LsbIdxOfTmstmpValOnTmln`` to index into - /// the LSB of a particular timestamp encoded as the - /// minimum length u8 sequence within + /// we could do Vec<(LsbIdxOfTmstmpValOnTmln, u8)>, but I + /// suspect that Vec is more cache + /// friendly. We use ``LsbIdxOfTmstmpValOnTmln`` to index into + /// the LSB of a particular timestamp encoded as the + /// minimum length u8 sequence within /// ``vcd.tmstmps_encoded_as_u8s``, and we use the values in - /// ``byte_len_of_num_tmstmp_vals_on_tmln`` to determine how + /// ``byte_len_of_num_tmstmp_vals_on_tmln`` to determine how /// many u8 values a particular timestamp is composed of. lsb_indxs_of_num_tmstmp_vals_on_tmln: Vec, byte_len_of_num_tmstmp_vals_on_tmln: Vec, @@ -179,11 +187,11 @@ type SignalValNum = BigUint; impl SignalEnum { pub fn name(&self) -> String { match self { - SignalEnum::Data { name, ..} => name, - SignalEnum::Alias { name, .. } => name - }.clone() + SignalEnum::Data { name, .. } => name, + SignalEnum::Alias { name, .. } => name, + } + .clone() } - } // helper functions ultimately used by Signal's query functions later on @@ -256,8 +264,8 @@ impl SignalEnum { /// global timeline field of a VCD struct instance) and computes /// the time pointed at by event_idx. /// This function also uses the same idx to index into the - /// nums_encoded_as_fixed_width_le_u8 and - /// byte_len_of_num_tmstmp_vals_on_tmln fields of an instance + /// nums_encoded_as_fixed_width_le_u8 and + /// byte_len_of_num_tmstmp_vals_on_tmln fields of an instance /// of the Signal::Data variant to compute the signal's corresponding /// numerical value at the time pointed at by event_didx. /// The function returns a tuple of the timestamp and numerical @@ -311,7 +319,7 @@ impl SignalEnum { fn bits_required(&self) -> Option { match self { - SignalEnum::Data {num_bits, ..} => num_bits.clone(), + SignalEnum::Data { num_bits, .. } => num_bits.clone(), // TODO: Follow aliases? SignalEnum::Alias { .. } => None, } @@ -337,7 +345,7 @@ impl SignalEnum { Self::Alias { name: _, signal_alias, - path: _ + path: _, } => { let SignalIdx(idx) = signal_alias; *idx @@ -350,20 +358,15 @@ impl SignalEnum { // 2. the vector of indices into timeline where events occur // for this signal // else we propagate Err(..). - let (string_vals, lsb_indxs_of_string_tmstmp_vals_on_tmln) = - match &all_signals[signal_idx] { - SignalEnum::Data { - ref string_vals, - ref lsb_indxs_of_string_tmstmp_vals_on_tmln, - .. - } => { - Ok(( - string_vals, - lsb_indxs_of_string_tmstmp_vals_on_tmln, - )) - } - SignalEnum::Alias { .. } => Err(SignalErrors::PointsToAlias), - }?; + let (string_vals, lsb_indxs_of_string_tmstmp_vals_on_tmln) = match &all_signals[signal_idx] + { + SignalEnum::Data { + ref string_vals, + ref lsb_indxs_of_string_tmstmp_vals_on_tmln, + .. + } => Ok((string_vals, lsb_indxs_of_string_tmstmp_vals_on_tmln)), + SignalEnum::Alias { .. } => Err(SignalErrors::PointsToAlias), + }?; // this signal should at least have some events, otherwise, trying to index into // an empty vector later on would fail if lsb_indxs_of_string_tmstmp_vals_on_tmln.is_empty() { -- 2.47.1 From 03705f263d554ce1ba5c4b5a650c821b5e8438d5 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Wed, 13 Sep 2023 14:18:18 +0200 Subject: [PATCH 4/5] Allow comments in scope (fix typo) --- src/vcd/parse/scopes.rs | 2 +- tests/files.rs | 7 +- tests/vcd-files/scope_with_comment.vcd | 296 +++++++++++++++++++++++++ 3 files changed, 301 insertions(+), 4 deletions(-) create mode 100644 tests/vcd-files/scope_with_comment.vcd diff --git a/src/vcd/parse/scopes.rs b/src/vcd/parse/scopes.rs index c60deda..6a0f28c 100644 --- a/src/vcd/parse/scopes.rs +++ b/src/vcd/parse/scopes.rs @@ -386,7 +386,7 @@ pub(super) fn parse_scopes<'a, R: std::io::Read>( ident(word_reader, "$end")?; break; } - "comment" => { + "$comment" => { // although we don't store comments, we still need to advance the // word_reader cursor to the end of the comment loop { diff --git a/tests/files.rs b/tests/files.rs index f5d2ac3..7832a85 100644 --- a/tests/files.rs +++ b/tests/files.rs @@ -5,7 +5,7 @@ // TODO: we should eventually be able to only test on just // the files const -pub const FILES : [&str; 30] = [ +pub const FILES : [&str; 31] = [ "./tests/vcd-files/aldec/SPI_Write.vcd", "./tests/vcd-files/ghdl/alu.vcd", "./tests/vcd-files/ghdl/idea.vcd", @@ -36,7 +36,8 @@ pub const FILES : [&str; 30] = [ "./tests/vcd-files/xilinx_isim/test.vcd", "./tests/vcd-files/xilinx_isim/test1.vcd", // TODO : add signal ignore list to handle bitwidth mismatches - "./tests/vcd-files/xilinx_isim/test2x2_regex22_string1.vcd" + "./tests/vcd-files/xilinx_isim/test2x2_regex22_string1.vcd", + "./tests/vcd-files/scope_with_comment.vcd", ]; pub const GOOD_DATE_FILES : [&str; 24] = [ @@ -73,4 +74,4 @@ pub const BAD_DATE_FILES : [&str; 6] = [ "./test-vcd-files/systemc/waveform.vcd", "./test-vcd-files/treadle/GCD.vcd", "./test-vcd-files/vivado/iladata.vcd", -]; \ No newline at end of file +]; diff --git a/tests/vcd-files/scope_with_comment.vcd b/tests/vcd-files/scope_with_comment.vcd new file mode 100644 index 0000000..cf17910 --- /dev/null +++ b/tests/vcd-files/scope_with_comment.vcd @@ -0,0 +1,296 @@ +$date + Sat Dec 26 15:33:14 2020 +$end +$version + ModelSim Version 10.5b +$end +$timescale + 1ns +$end + +$scope module clkdiv2n_tb $end +$comment foo $end +$var reg 1 ! clk $end +$var reg 1 " reset $end +$var wire 1 # clk_out $end + +$scope module t1 $end +$var parameter 32 $ WIDTH $end +$var parameter 32 % N $end +$var wire 1 & clk $end +$var wire 1 ' reset $end +$var wire 1 # clk_out $end +$var reg 3 ( r_reg [2:0] $end +$var wire 1 ) r_nxt [2] $end +$var wire 1 * r_nxt [1] $end +$var wire 1 + r_nxt [0] $end +$var reg 1 , clk_track $end +$upscope $end +$comment foo $end +$upscope $end +$comment foo $end +$enddefinitions $end +#0 +$comment foo $end +$dumpvars +0! +x" +bx ( +x, +b11 $ +b110 % +x# +x+ +x* +x) +x' +0& +$end +#5 +1" +1' +b0 ( +0, +1+ +0* +0) +0# +#10 +1! +1& +#15 +0" +0' +#20 +0! +0& +#30 +1! +1& +b1 ( +0+ +1* +#40 +0! +0& +#50 +1! +1& +b10 ( +1+ +#60 +0! +0& +#70 +1! +1& +b11 ( +0+ +0* +1) +#80 +0! +0& +#90 +1! +1& +b100 ( +1+ +#100 +0! +0& +#110 +1! +1& +b101 ( +0+ +1* +#120 +0! +0& +#130 +1! +1& +b0 ( +1, +1+ +0* +0) +1# +#140 +0! +0& +#150 +1! +1& +b1 ( +0+ +1* +#160 +0! +0& +#170 +1! +1& +b10 ( +1+ +#180 +0! +0& +#190 +1! +1& +b11 ( +0+ +0* +1) +#200 +0! +0& +#210 +1! +1& +b100 ( +1+ +#220 +0! +0& +#230 +1! +1& +b101 ( +0+ +1* +#240 +0! +0& +#250 +1! +1& +b0 ( +0, +1+ +0* +0) +0# +#260 +0! +0& +#270 +1! +1& +b1 ( +0+ +1* +#280 +0! +0& +#290 +1! +1& +b10 ( +1+ +#300 +0! +0& +#310 +1! +1& +b11 ( +0+ +0* +1) +#320 +0! +0& +#330 +1! +1& +b100 ( +1+ +#340 +0! +0& +#350 +1! +1& +b101 ( +0+ +1* +#360 +0! +0& +#370 +1! +1& +b0 ( +1, +1+ +0* +0) +1# +#380 +0! +0& +#390 +1! +1& +b1 ( +0+ +1* +#400 +0! +0& +#410 +1! +1& +b10 ( +1+ +#420 +0! +0& +#430 +1! +1& +b11 ( +0+ +0* +1) +#440 +0! +0& +#450 +1! +1& +b100 ( +1+ +#460 +0! +0& +#470 +1! +1& +b101 ( +0+ +1* +#480 +0! +0& +#490 +1! +1& +b0 ( +0, +1+ +0* +0) +0# +#500 +0! +0& +#510 +1! +1& +b1 ( +0+ +1* -- 2.47.1 From 0897bbae663b427d1d7d5562955aa252cadc8a14 Mon Sep 17 00:00:00 2001 From: Oscar Gustafsson Date: Wed, 13 Sep 2023 13:24:13 +0200 Subject: [PATCH 5/5] Keep index as part of signal name --- src/vcd/parse/scopes.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/vcd/parse/scopes.rs b/src/vcd/parse/scopes.rs index c60deda..ce97277 100644 --- a/src/vcd/parse/scopes.rs +++ b/src/vcd/parse/scopes.rs @@ -98,11 +98,7 @@ pub(super) fn parse_var<'a, R: std::io::Read>( let (word, _) = next_word!(word_reader)?; match word { "$end" => break, - other => { - if !other.starts_with("[") { - full_signal_name.push(word.to_string()) - } - } + _ => full_signal_name.push(word.to_string()) } } let full_signal_name = full_signal_name.join(" "); -- 2.47.1