From 8dab46a0cbaad498f9cf41484558ac14c0337217 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Sun, 21 Aug 2022 19:51:51 -0400 Subject: [PATCH 1/9] - moved dereferencing alias to VCD impl - added function to help with reconstructing timestamps and numerical signal values --- src/vcd/signal.rs | 256 +++++++++++++++++++++++++++++++++++++------ src/vcd/types.rs | 34 ++++++ src/vcd/utilities.rs | 110 ------------------- 3 files changed, 257 insertions(+), 143 deletions(-) diff --git a/src/vcd/signal.rs b/src/vcd/signal.rs index fd9fc92..daefc44 100644 --- a/src/vcd/signal.rs +++ b/src/vcd/signal.rs @@ -68,30 +68,25 @@ pub(super) enum Signal { }, } +#[derive(Debug)] +pub(super) enum LookupErrors { + PreTimeline { + desired_time: BigUint, + timeline_start_time: BigUint, + }, + EmptyTimeline, + TimelineNotMultiple, + OrderingFailure, + PointsToAlias, + NoNumBits, + Other(String), +} + +// these are thin type aliases primarily to make code more readable later on +type TimeStamp = BigUint; +type SignalValNum = BigUint; + impl Signal { - pub(super) fn try_dereference_alias<'a>( - &'a self, - signals: &'a Vec, - ) -> Result<&Signal, String> { - // dereference a signal if we need to and return a signal, else return - // the signal itself - let signal = match self { - Signal::Data { .. } => self, - Signal::Alias { name, signal_alias } => { - let SignalIdx(idx) = signal_alias; - &signals[*idx] - } - }; - match signal { - Signal::Data { .. } => Ok(signal), - Signal::Alias { .. } => Err(format!( - "Error near {}:{}. A signal alias shouldn't \ - point to a signal alias.", - file!(), - line!() - )), - } - } pub(super) fn bytes_required(num_bits: &Option, name: &String) -> Result { let num_bits = num_bits .ok_or_else(|| format!("Error near {}:{}. num_bits empty.", file!(), line!()))?; @@ -106,15 +101,210 @@ impl Signal { })?; Ok(bytes_required) } - pub(super) fn query_value(&self, time: BigUint) -> Result { - // match - // assert - // ordered_binary_lookup_u8( - // &value_sequence_as_bytes_u8, - // 4, - // &timeline_cursors, - // TimelineIdx(scrubbing_cursor), - // ); - Ok(TimelineQueryResults::String("".to_string())) + pub fn lookup_time_and_val( + &self, + idx: usize, + tmstmps_encoded_as_u8s: &Vec, + ) -> Result<(TimeStamp, SignalValNum), LookupErrors> { + let ( + name, + num_bits, + nums_encoded_as_fixed_width_le_u8, + lsb_indxs_of_num_tmstmp_vals_on_tmln, + byte_len_of_num_tmstmp_vals_on_tmln, + ) = match self { + Signal::Data { + name, + sig_type, + signal_error, + num_bits, + self_idx, + nums_encoded_as_fixed_width_le_u8, + string_vals, + lsb_indxs_of_num_tmstmp_vals_on_tmln, + byte_len_of_num_tmstmp_vals_on_tmln, + lsb_indxs_of_string_tmstmp_vals_on_tmln, + byte_len_of_string_tmstmp_vals_on_tmln, + scope_parent, + } => Ok(( + name, + num_bits, + nums_encoded_as_fixed_width_le_u8, + lsb_indxs_of_num_tmstmp_vals_on_tmln, + byte_len_of_num_tmstmp_vals_on_tmln, + )), + Signal::Alias { name, signal_alias } => Err(LookupErrors::PointsToAlias), + }?; + + // get index + let LsbIdxOfTmstmpValOnTmln(timestamp_idx) = lsb_indxs_of_num_tmstmp_vals_on_tmln[idx]; + let timestamp_idx = timestamp_idx as usize; + + // form timestamp + let byte_len = byte_len_of_num_tmstmp_vals_on_tmln[timestamp_idx] as usize; + let timestamp = &tmstmps_encoded_as_u8s[timestamp_idx..(timestamp_idx + byte_len)]; + let timestamp = BigUint::from_bytes_le(timestamp); + + // get signal value + let bytes_per_value = + Signal::bytes_required(num_bits, name).map_err(|e| LookupErrors::Other(e))?; + let bytes_per_value = byte_len as usize; + let start_idx = idx * bytes_per_value; + let end_idx = (idx + 1) * bytes_per_value; + let signal_val = &nums_encoded_as_fixed_width_le_u8[start_idx..end_idx]; + let signal_val = BigUint::from_bytes_le(signal_val); + + Ok((timestamp, signal_val)) } + // pub(super) fn query_num_val_on_tmln( + // &self, + // //(REMOVE THIS COMMENT)below is from self + // nums_encoded_as_fixed_width_le_u8: &Vec, + // lsb_indxs_of_num_tmstmp_vals_on_tmln: &Vec, + // tmstmps_encoded_as_u8s: &Vec, + // all_signals: &Vec, + // //(REMOVE THIS COMMENT)below is from self + // // TODO : should this be usize? + // desired_time: BigUint, + // ) -> Result { + // let signal_idx = match self { + // Self::Data { + // name, + // sig_type, + // signal_error, + // num_bits, + // self_idx, + // .. + // } => { + // let SignalIdx(idx) = self_idx; + // *idx + // } + // Self::Alias { name, signal_alias } => { + // let SignalIdx(idx) = signal_alias; + // *idx + // } + // }; + + // let ( + // nums_encoded_as_fixed_width_le_u8, + // lsb_indxs_of_num_tmstmp_vals_on_tmln, + // tmstmps_encoded_as_u8s, + // num_bits, + // name, + // ) = match all_signals[signal_idx] { + // Signal::Data { + // name, + // sig_type, + // signal_error, + // num_bits, + // self_idx, + // ref nums_encoded_as_fixed_width_le_u8, + // string_vals, + // ref lsb_indxs_of_num_tmstmp_vals_on_tmln, + // byte_len_of_num_tmstmp_vals_on_tmln, + // lsb_indxs_of_string_tmstmp_vals_on_tmln, + // byte_len_of_string_tmstmp_vals_on_tmln, + // scope_parent, + // } => { + // if num_bits.is_none() { + // return Err(LookupErrors::NoNumBits); + // } + // Ok(( + // nums_encoded_as_fixed_width_le_u8, + // lsb_indxs_of_num_tmstmp_vals_on_tmln, + // tmstmps_encoded_as_u8s, + // num_bits, + // name, + // )) + // } + // Signal::Alias { name, signal_alias } => Err(LookupErrors::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_num_tmstmp_vals_on_tmln.is_empty() { + // return Err(LookupErrors::EmptyTimeline); + // } + + // // assertion that value_sequence is a proper multiple of + // // timeline_markers + // let bytes_required = + // Signal::bytes_required(&num_bits, &name).map_err(|arg| LookupErrors::Other(arg))?; + // if lsb_indxs_of_num_tmstmp_vals_on_tmln.len() + // != (nums_encoded_as_fixed_width_le_u8.len() * bytes_required as usize) + // { + // return Err(LookupErrors::TimelineNotMultiple); + // } + + // // let TimelineIdx(desired_time) = desired_time; + + // // check if we're requesting a value that occurs before the recorded + // // start of the timeline + // let TimelineIdx(timeline_start_time) = timeline_cursors.first().unwrap(); + // if desired_time < *timeline_start_time { + // return Err(LookupErrors::PreTimeline { + // desired_time: TimelineIdx(desired_time), + // timeline_start_time: TimelineIdx(*timeline_start_time), + // }); + // } + + // let mut lower_idx = 0usize; + // let mut upper_idx = timeline_cursors.len() - 1; + + // // check if we're requesting a value that occurs beyond the end of the timeline, + // // if so, return the last value in this timeline + // let TimelineIdx(timeline_end_time) = timeline_cursors.last().unwrap(); + // if desired_time > *timeline_end_time { + // let range = (value_sequence_as_bytes.len() - bytes_per_value)..; + // let value_by_bytes = &value_sequence_as_bytes[range]; + // let value = BigUint::from_bytes_le(value_by_bytes); + + // return Ok(value); + // } + + // // This while loop is the meat of the lookup. Performance is log2(n), + // // where n is the number of events on the timeline. + // // We can assume that by the time we get here, that the desired_time + // // is an event that occurs on the timeline, given that we handle any events + // // occuring after or before the recorded tiimeline in the code above. + // while lower_idx <= upper_idx { + // let mid_idx = lower_idx + ((upper_idx - lower_idx) / 2); + // let TimelineIdx(curr_time) = timeline_cursors[mid_idx]; + // let ordering = curr_time.cmp(&desired_time); + + // match ordering { + // std::cmp::Ordering::Less => { + // lower_idx = mid_idx + 1; + // } + // std::cmp::Ordering::Equal => { + // let u8_timeline_start_idx = mid_idx * bytes_per_value; + // let u8_timeline_end_idx = u8_timeline_start_idx + bytes_per_value; + // let range = u8_timeline_start_idx..u8_timeline_end_idx; + // let value_by_bytes = &value_sequence_as_bytes[range]; + // let value = BigUint::from_bytes_le(value_by_bytes); + // return Ok(value); + // } + // std::cmp::Ordering::Greater => { + // upper_idx = mid_idx - 1; + // } + // } + // } + + // let idx = lower_idx - 1; + // let TimelineIdx(left_time) = timeline_cursors[idx]; + // let TimelineIdx(right_time) = timeline_cursors[idx + 1]; + + // let ordered_left = left_time < desired_time; + // let ordered_right = desired_time < right_time; + // if !(ordered_left && ordered_right) { + // return Err(LookupErrors::OrderingFailure); + // } + + // let u8_timeline_start_idx = idx * bytes_per_value; + // let u8_timeline_end_idx = u8_timeline_start_idx + bytes_per_value; + // let range = u8_timeline_start_idx..u8_timeline_end_idx; + // let value_by_bytes = &value_sequence_as_bytes[range]; + // let value = BigUint::from_bytes_le(value_by_bytes); + + // return Ok(value); + // } } diff --git a/src/vcd/types.rs b/src/vcd/types.rs index 93ceee7..12f9af1 100644 --- a/src/vcd/types.rs +++ b/src/vcd/types.rs @@ -99,4 +99,38 @@ impl VCD { )), } } + pub(super) fn try_dereference_alias<'a>( + &'a self, + idx: &SignalIdx, + ) -> Result<&'a Signal, String> { + // get the signal pointed to be SignalIdx from the arena + let SignalIdx(idx) = idx; + let signal = &self.all_signals[*idx]; + + // dereference signal if Signal::Alias, or keep idx if Signal::Data + let signal_idx = match signal { + Signal::Data { + name, + sig_type, + signal_error, + num_bits, + self_idx, + .. + } => *self_idx, + Signal::Alias { name, signal_alias } => *signal_alias, + }; + + // Should now point to Signal::Data variant, or else there's an error + let SignalIdx(idx) = signal_idx; + let signal = self.all_signals.get(idx).unwrap(); + match signal { + Signal::Data { .. } => Ok(signal), + Signal::Alias { .. } => Err(format!( + "Error near {}:{}. A signal alias shouldn't \ + point to a signal alias.", + file!(), + line!() + )), + } + } } diff --git a/src/vcd/utilities.rs b/src/vcd/utilities.rs index a8e20aa..5df9160 100644 --- a/src/vcd/utilities.rs +++ b/src/vcd/utilities.rs @@ -74,113 +74,3 @@ pub(super) fn binary_str_to_vec_u8(binary_str: &str) -> Result, BinaryPa } Ok(vec_u8) } - -use num::{BigUint, Zero}; - -#[derive(Debug)] -pub(super) enum LookupErrors { - PreTimeline { - desired_time: BigUint, - timeline_start_time: BigUint, - }, - EmptyTimeline, - TimelineNotMultiple, - OrderingFailure, -} - -// pub(super) fn ordered_binary_lookup_u8( -// //(REMOVE THIS COMMENT)below is from self -// lsb_indxs_of_num_tmstmp_vals_on_tmln: &Vec, -// tmstmps_encoded_as_u8s: &Vec, -// //(REMOVE THIS COMMENT)below is from self -// nums_encoded_as_fixed_width_le_u8: &Vec, -// // TODO : should this be usize? -// bytes_per_value: usize, -// desired_time: BigUint, -// ) -> Result { -// // this signal should at least have some events, otherwise, trying to index into -// // an empty vector later on would fail -// if lsb_indxs_of_num_tmstmp_vals_on_tmln.is_empty() { -// return Err(LookupErrors::EmptyTimeline); -// } - -// // assertion that value_sequence is a proper multiple of -// // timeline_markers -// if lsb_indxs_of_num_tmstmp_vals_on_tmln.len() -// != (nums_encoded_as_fixed_width_le_u8.len() * bytes_per_value) -// { -// return Err(LookupErrors::TimelineNotMultiple); -// } - -// // let TimelineIdx(desired_time) = desired_time; - -// // check if we're requesting a value that occurs before the recorded -// // start of the timeline -// let TimelineIdx(timeline_start_time) = timeline_cursors.first().unwrap(); -// if desired_time < *timeline_start_time { -// return Err(LookupErrors::PreTimeline { -// desired_time: TimelineIdx(desired_time), -// timeline_start_time: TimelineIdx(*timeline_start_time), -// }); -// } - -// let mut lower_idx = 0usize; -// let mut upper_idx = timeline_cursors.len() - 1; - -// // check if we're requesting a value that occurs beyond the end of the timeline, -// // if so, return the last value in this timeline -// let TimelineIdx(timeline_end_time) = timeline_cursors.last().unwrap(); -// if desired_time > *timeline_end_time { -// let range = (value_sequence_as_bytes.len() - bytes_per_value)..; -// let value_by_bytes = &value_sequence_as_bytes[range]; -// let value = BigUint::from_bytes_le(value_by_bytes); - -// return Ok(value); -// } - -// // This while loop is the meat of the lookup. Performance is log2(n), -// // where n is the number of events on the timeline. -// // We can assume that by the time we get here, that the desired_time -// // is an event that occurs on the timeline, given that we handle any events -// // occuring after or before the recorded tiimeline in the code above. -// while lower_idx <= upper_idx { -// let mid_idx = lower_idx + ((upper_idx - lower_idx) / 2); -// let TimelineIdx(curr_time) = timeline_cursors[mid_idx]; -// let ordering = curr_time.cmp(&desired_time); - -// match ordering { -// std::cmp::Ordering::Less => { -// lower_idx = mid_idx + 1; -// } -// std::cmp::Ordering::Equal => { -// let u8_timeline_start_idx = mid_idx * bytes_per_value; -// let u8_timeline_end_idx = u8_timeline_start_idx + bytes_per_value; -// let range = u8_timeline_start_idx..u8_timeline_end_idx; -// let value_by_bytes = &value_sequence_as_bytes[range]; -// let value = BigUint::from_bytes_le(value_by_bytes); -// return Ok(value); -// } -// std::cmp::Ordering::Greater => { -// upper_idx = mid_idx - 1; -// } -// } -// } - -// let idx = lower_idx - 1; -// let TimelineIdx(left_time) = timeline_cursors[idx]; -// let TimelineIdx(right_time) = timeline_cursors[idx + 1]; - -// let ordered_left = left_time < desired_time; -// let ordered_right = desired_time < right_time; -// if !(ordered_left && ordered_right) { -// return Err(LookupErrors::OrderingFailure); -// } - -// let u8_timeline_start_idx = idx * bytes_per_value; -// let u8_timeline_end_idx = u8_timeline_start_idx + bytes_per_value; -// let range = u8_timeline_start_idx..u8_timeline_end_idx; -// let value_by_bytes = &value_sequence_as_bytes[range]; -// let value = BigUint::from_bytes_le(value_by_bytes); - -// return Ok(value); -// } -- 2.47.1 From 91dc24a9ba18cce24fef140a4780359f6683eec6 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Mon, 22 Aug 2022 09:48:56 -0400 Subject: [PATCH 2/9] Compute num_bytes ahead of time; Start removing undeeded signals from match arms --- src/vcd/parse/events.rs | 35 ++++++++++++++++++----------------- src/vcd/parse/scopes.rs | 8 ++++++++ src/vcd/signal.rs | 30 ++++++++++-------------------- 3 files changed, 36 insertions(+), 37 deletions(-) diff --git a/src/vcd/parse/events.rs b/src/vcd/parse/events.rs index 9dfb319..9213af1 100644 --- a/src/vcd/parse/events.rs +++ b/src/vcd/parse/events.rs @@ -121,6 +121,7 @@ pub(super) fn parse_events<'a>( sig_type, ref mut signal_error, num_bits, + num_bytes, self_idx, nums_encoded_as_fixed_width_le_u8, string_vals, @@ -190,7 +191,9 @@ pub(super) fn parse_events<'a>( // so that we end up storing all values // of a particular signal in a consistent // amount of bytes - let bytes_required = Signal::bytes_required(num_bits, name)?; + let bytes_required = num_bytes.ok_or_else(|| { + format!("Error near {}:{}. num_bytes empty.", file!(), line!()) + })?; while curr_num_bytes < bytes_required { nums_encoded_as_fixed_width_le_u8.push(0u8); @@ -230,14 +233,13 @@ pub(super) fn parse_events<'a>( sig_type, ref mut signal_error, num_bits, - self_idx, + num_bytes: _, + self_idx: _, nums_encoded_as_fixed_width_le_u8, - string_vals, + string_vals: _, lsb_indxs_of_num_tmstmp_vals_on_tmln, byte_len_of_num_tmstmp_vals_on_tmln, - lsb_indxs_of_string_tmstmp_vals_on_tmln, - byte_len_of_string_tmstmp_vals_on_tmln, - scope_parent, + .. } => { // if this is a bad signal, go ahead and skip it if signal_error.is_some() { @@ -309,14 +311,13 @@ pub(super) fn parse_events<'a>( sig_type, ref mut signal_error, num_bits, - self_idx, + num_bytes: _, + self_idx: _, nums_encoded_as_fixed_width_le_u8, - string_vals, + string_vals: _, lsb_indxs_of_num_tmstmp_vals_on_tmln, byte_len_of_num_tmstmp_vals_on_tmln, - lsb_indxs_of_string_tmstmp_vals_on_tmln, - byte_len_of_string_tmstmp_vals_on_tmln, - scope_parent, + .. } => { // if this is a bad signal, go ahead and skip it if signal_error.is_some() { @@ -390,14 +391,14 @@ pub(super) fn parse_events<'a>( sig_type, ref mut signal_error, num_bits, - self_idx, - nums_encoded_as_fixed_width_le_u8, + num_bytes: _, + self_idx: _, + nums_encoded_as_fixed_width_le_u8: _, string_vals, - lsb_indxs_of_num_tmstmp_vals_on_tmln, - byte_len_of_num_tmstmp_vals_on_tmln, + lsb_indxs_of_num_tmstmp_vals_on_tmln: _, + byte_len_of_num_tmstmp_vals_on_tmln: _, lsb_indxs_of_string_tmstmp_vals_on_tmln, - byte_len_of_string_tmstmp_vals_on_tmln, - scope_parent, + .. } => { // if this is a bad signal, go ahead and skip it if signal_error.is_some() { diff --git a/src/vcd/parse/scopes.rs b/src/vcd/parse/scopes.rs index 6d69ee8..0657ea7 100644 --- a/src/vcd/parse/scopes.rs +++ b/src/vcd/parse/scopes.rs @@ -89,6 +89,13 @@ pub(super) fn parse_var<'a>( } let full_signal_name = full_signal_name.join(" "); + let num_bytes = if no_bits.is_some() { + let bytes_required = Signal::bytes_required(no_bits.unwrap(), &full_signal_name)?; + Some(bytes_required) + } else { + None + }; + // Is the current variable an alias to a signal already encountered? // if so, handle ref_signal_idx accordingly, if not, add signal to hash // map @@ -109,6 +116,7 @@ pub(super) fn parse_var<'a>( sig_type: var_type, signal_error: None, num_bits: no_bits, + num_bytes: num_bytes, self_idx: signal_idx, nums_encoded_as_fixed_width_le_u8: vec![], string_vals: vec![], diff --git a/src/vcd/signal.rs b/src/vcd/signal.rs index daefc44..90a9743 100644 --- a/src/vcd/signal.rs +++ b/src/vcd/signal.rs @@ -36,6 +36,7 @@ pub(super) enum Signal { // errors in the following type: signal_error: Option, num_bits: Option, + num_bytes: Option, // TODO : may be able to remove self_idx self_idx: SignalIdx, // A signal may take on a new value and hold that value @@ -79,6 +80,7 @@ pub(super) enum LookupErrors { OrderingFailure, PointsToAlias, NoNumBits, + NoNumBytes, Other(String), } @@ -87,9 +89,7 @@ type TimeStamp = BigUint; type SignalValNum = BigUint; impl Signal { - pub(super) fn bytes_required(num_bits: &Option, name: &String) -> Result { - let num_bits = num_bits - .ok_or_else(|| format!("Error near {}:{}. num_bits empty.", file!(), line!()))?; + pub(super) fn bytes_required(num_bits: u16, name: &String) -> Result { let bytes_required = (num_bits / 8) + if (num_bits % 8) > 0 { 1 } else { 0 }; let bytes_required = u8::try_from(bytes_required).map_err(|_| { format!( @@ -107,33 +107,24 @@ impl Signal { tmstmps_encoded_as_u8s: &Vec, ) -> Result<(TimeStamp, SignalValNum), LookupErrors> { let ( - name, - num_bits, + num_bytes, nums_encoded_as_fixed_width_le_u8, lsb_indxs_of_num_tmstmp_vals_on_tmln, byte_len_of_num_tmstmp_vals_on_tmln, ) = match self { Signal::Data { - name, - sig_type, - signal_error, - num_bits, - self_idx, + num_bytes, nums_encoded_as_fixed_width_le_u8, - string_vals, lsb_indxs_of_num_tmstmp_vals_on_tmln, byte_len_of_num_tmstmp_vals_on_tmln, - lsb_indxs_of_string_tmstmp_vals_on_tmln, - byte_len_of_string_tmstmp_vals_on_tmln, - scope_parent, + .. } => Ok(( - name, - num_bits, + num_bytes, nums_encoded_as_fixed_width_le_u8, lsb_indxs_of_num_tmstmp_vals_on_tmln, byte_len_of_num_tmstmp_vals_on_tmln, )), - Signal::Alias { name, signal_alias } => Err(LookupErrors::PointsToAlias), + Signal::Alias { .. } => Err(LookupErrors::PointsToAlias), }?; // get index @@ -146,9 +137,8 @@ impl Signal { let timestamp = BigUint::from_bytes_le(timestamp); // get signal value - let bytes_per_value = - Signal::bytes_required(num_bits, name).map_err(|e| LookupErrors::Other(e))?; - let bytes_per_value = byte_len as usize; + let bytes_per_value = num_bytes.ok_or_else(|| LookupErrors::NoNumBytes)?; + let bytes_per_value = bytes_per_value as usize; let start_idx = idx * bytes_per_value; let end_idx = (idx + 1) * bytes_per_value; let signal_val = &nums_encoded_as_fixed_width_le_u8[start_idx..end_idx]; -- 2.47.1 From 0acd49f66c63bc43cce2b02ebb3a9dc39bd96620 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Mon, 22 Aug 2022 09:56:22 -0400 Subject: [PATCH 3/9] correct lengths of u8 LE encoded timestamp being recorded onto byte_len_of_(num/string)_tmstmp_vals_on_tmln --- src/vcd/parse/events.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/vcd/parse/events.rs b/src/vcd/parse/events.rs index 9213af1..48f3320 100644 --- a/src/vcd/parse/events.rs +++ b/src/vcd/parse/events.rs @@ -199,7 +199,7 @@ pub(super) fn parse_events<'a>( nums_encoded_as_fixed_width_le_u8.push(0u8); curr_num_bytes += 1; } - byte_len_of_num_tmstmp_vals_on_tmln.push(curr_num_bytes); + byte_len_of_num_tmstmp_vals_on_tmln.push(curr_tmstmp_len_u8); Ok(()) } } @@ -279,7 +279,7 @@ pub(super) fn parse_events<'a>( nums_encoded_as_fixed_width_le_u8.push(0u8); lsb_indxs_of_num_tmstmp_vals_on_tmln .push(LsbIdxOfTmstmpValOnTmln(curr_tmstmp_lsb_idx)); - byte_len_of_num_tmstmp_vals_on_tmln.push(1u8); + byte_len_of_num_tmstmp_vals_on_tmln.push(curr_tmstmp_len_u8); Ok(()) } Signal::Alias { .. } => { @@ -357,7 +357,7 @@ pub(super) fn parse_events<'a>( nums_encoded_as_fixed_width_le_u8.push(1u8); lsb_indxs_of_num_tmstmp_vals_on_tmln .push(LsbIdxOfTmstmpValOnTmln(curr_tmstmp_lsb_idx)); - byte_len_of_num_tmstmp_vals_on_tmln.push(1u8); + byte_len_of_num_tmstmp_vals_on_tmln.push(curr_tmstmp_len_u8); Ok(()) } Signal::Alias { .. } => { @@ -396,7 +396,7 @@ pub(super) fn parse_events<'a>( nums_encoded_as_fixed_width_le_u8: _, string_vals, lsb_indxs_of_num_tmstmp_vals_on_tmln: _, - byte_len_of_num_tmstmp_vals_on_tmln: _, + byte_len_of_num_tmstmp_vals_on_tmln, lsb_indxs_of_string_tmstmp_vals_on_tmln, .. } => { @@ -438,6 +438,7 @@ pub(super) fn parse_events<'a>( string_vals.push(val); lsb_indxs_of_string_tmstmp_vals_on_tmln .push(LsbIdxOfTmstmpValOnTmln(curr_tmstmp_lsb_idx)); + byte_len_of_num_tmstmp_vals_on_tmln.push(curr_tmstmp_len_u8); Ok(()) } Signal::Alias { .. } => { -- 2.47.1 From 37cf2b165c55e192cc71fc42bd39bfd4527cb820 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Mon, 22 Aug 2022 10:03:29 -0400 Subject: [PATCH 4/9] remove some unused fields from struct match arms and eliminate warning in main --- src/main.rs | 2 +- src/vcd/parse/events.rs | 14 +------------- src/vcd/types.rs | 18 ++---------------- src/vcd/utilities.rs | 2 -- 4 files changed, 4 insertions(+), 32 deletions(-) diff --git a/src/main.rs b/src/main.rs index b8442c6..2f82089 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,7 +20,7 @@ fn main() -> std::io::Result<()> { let now = Instant::now(); let file = File::open(&args.path)?; - let vcd = parse_vcd(file).unwrap(); + parse_vcd(file).unwrap(); let elapsed = now.elapsed(); println!("Elapsed: {:.2?}", elapsed); diff --git a/src/vcd/parse/events.rs b/src/vcd/parse/events.rs index 48f3320..8e3d18b 100644 --- a/src/vcd/parse/events.rs +++ b/src/vcd/parse/events.rs @@ -122,14 +122,12 @@ pub(super) fn parse_events<'a>( ref mut signal_error, num_bits, num_bytes, - self_idx, nums_encoded_as_fixed_width_le_u8, string_vals, lsb_indxs_of_num_tmstmp_vals_on_tmln, byte_len_of_num_tmstmp_vals_on_tmln, lsb_indxs_of_string_tmstmp_vals_on_tmln, - byte_len_of_string_tmstmp_vals_on_tmln, - scope_parent, + .. } => { // we've already identified in a prior loop iteration that the signal has // an error @@ -233,10 +231,7 @@ pub(super) fn parse_events<'a>( sig_type, ref mut signal_error, num_bits, - num_bytes: _, - self_idx: _, nums_encoded_as_fixed_width_le_u8, - string_vals: _, lsb_indxs_of_num_tmstmp_vals_on_tmln, byte_len_of_num_tmstmp_vals_on_tmln, .. @@ -311,10 +306,7 @@ pub(super) fn parse_events<'a>( sig_type, ref mut signal_error, num_bits, - num_bytes: _, - self_idx: _, nums_encoded_as_fixed_width_le_u8, - string_vals: _, lsb_indxs_of_num_tmstmp_vals_on_tmln, byte_len_of_num_tmstmp_vals_on_tmln, .. @@ -391,11 +383,7 @@ pub(super) fn parse_events<'a>( sig_type, ref mut signal_error, num_bits, - num_bytes: _, - self_idx: _, - nums_encoded_as_fixed_width_le_u8: _, string_vals, - lsb_indxs_of_num_tmstmp_vals_on_tmln: _, byte_len_of_num_tmstmp_vals_on_tmln, lsb_indxs_of_string_tmstmp_vals_on_tmln, .. diff --git a/src/vcd/types.rs b/src/vcd/types.rs index 12f9af1..6a48e4d 100644 --- a/src/vcd/types.rs +++ b/src/vcd/types.rs @@ -75,14 +75,7 @@ impl VCD { // dereference signal if Signal::Alias, or keep idx if Signal::Data let signal_idx = match signal { - Signal::Data { - name, - sig_type, - signal_error, - num_bits, - self_idx, - .. - } => *self_idx, + Signal::Data { self_idx, .. } => *self_idx, Signal::Alias { name, signal_alias } => *signal_alias, }; @@ -109,14 +102,7 @@ impl VCD { // dereference signal if Signal::Alias, or keep idx if Signal::Data let signal_idx = match signal { - Signal::Data { - name, - sig_type, - signal_error, - num_bits, - self_idx, - .. - } => *self_idx, + Signal::Data { self_idx, .. } => *self_idx, Signal::Alias { name, signal_alias } => *signal_alias, }; diff --git a/src/vcd/utilities.rs b/src/vcd/utilities.rs index 5df9160..a34905c 100644 --- a/src/vcd/utilities.rs +++ b/src/vcd/utilities.rs @@ -1,5 +1,3 @@ -use super::*; - #[derive(Debug)] pub(super) enum BinaryParserErrTypes { XValue, -- 2.47.1 From 3d2b7f80286d07cbb7ea4df77d3053616f05a924 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Mon, 22 Aug 2022 10:08:27 -0400 Subject: [PATCH 5/9] maintain consistency wit num_bits naming --- src/vcd/parse/scopes.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/vcd/parse/scopes.rs b/src/vcd/parse/scopes.rs index 0657ea7..a4cfc07 100644 --- a/src/vcd/parse/scopes.rs +++ b/src/vcd/parse/scopes.rs @@ -48,8 +48,8 @@ pub(super) fn parse_var<'a>( let parse_err = format!("failed to parse as usize on {cursor:?}"); // $var parameter 3 a IDLE $end - // ^ - no_bits - let no_bits = match var_type { + // ^ - num_bits + let num_bits = match var_type { SigType::Integer | SigType::Parameter | SigType::Real @@ -57,16 +57,16 @@ pub(super) fn parse_var<'a>( | SigType::Wire | SigType::Tri1 | SigType::Time => { - let no_bits = word.parse::().expect(parse_err.as_str()); - let no_bits = u16::try_from(no_bits).map_err(|_| { + let num_bits = word.parse::().expect(parse_err.as_str()); + let num_bits = u16::try_from(num_bits).map_err(|_| { format!( "Error near {}:{} while parsing vcd file at {cursor:?}. \ - This signal has {no_bits} > 2^16 - 1 bits.", + This signal has {num_bits} > 2^16 - 1 bits.", file!(), line!() ) })?; - Some(no_bits) + Some(num_bits) } // for strings, we don't really care what the number of bits is _ => None, @@ -89,8 +89,8 @@ pub(super) fn parse_var<'a>( } let full_signal_name = full_signal_name.join(" "); - let num_bytes = if no_bits.is_some() { - let bytes_required = Signal::bytes_required(no_bits.unwrap(), &full_signal_name)?; + let num_bytes = if num_bits.is_some() { + let bytes_required = Signal::bytes_required(num_bits.unwrap(), &full_signal_name)?; Some(bytes_required) } else { None @@ -115,7 +115,7 @@ pub(super) fn parse_var<'a>( name: full_signal_name, sig_type: var_type, signal_error: None, - num_bits: no_bits, + num_bits: num_bits, num_bytes: num_bytes, self_idx: signal_idx, nums_encoded_as_fixed_width_le_u8: vec![], -- 2.47.1 From fd60e95961a7a66b6be3fb0e0efe19f39fafec6e Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Mon, 22 Aug 2022 10:11:19 -0400 Subject: [PATCH 6/9] change lookup_errors to signal_errors --- src/vcd/signal.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/vcd/signal.rs b/src/vcd/signal.rs index 90a9743..c158601 100644 --- a/src/vcd/signal.rs +++ b/src/vcd/signal.rs @@ -1,4 +1,3 @@ -// use super::utilities::{ordered_binary_lookup_u8, LookupErrors}; use super::{ScopeIdx, SignalIdx}; use num::{BigUint, Zero}; @@ -70,7 +69,7 @@ pub(super) enum Signal { } #[derive(Debug)] -pub(super) enum LookupErrors { +pub(super) enum SignalErrors { PreTimeline { desired_time: BigUint, timeline_start_time: BigUint, @@ -105,7 +104,7 @@ impl Signal { &self, idx: usize, tmstmps_encoded_as_u8s: &Vec, - ) -> Result<(TimeStamp, SignalValNum), LookupErrors> { + ) -> Result<(TimeStamp, SignalValNum), SignalErrors> { let ( num_bytes, nums_encoded_as_fixed_width_le_u8, @@ -124,7 +123,7 @@ impl Signal { lsb_indxs_of_num_tmstmp_vals_on_tmln, byte_len_of_num_tmstmp_vals_on_tmln, )), - Signal::Alias { .. } => Err(LookupErrors::PointsToAlias), + Signal::Alias { .. } => Err(SignalErrors::PointsToAlias), }?; // get index @@ -137,7 +136,7 @@ impl Signal { let timestamp = BigUint::from_bytes_le(timestamp); // get signal value - let bytes_per_value = num_bytes.ok_or_else(|| LookupErrors::NoNumBytes)?; + let bytes_per_value = num_bytes.ok_or_else(|| SignalErrors::NoNumBytes)?; let bytes_per_value = bytes_per_value as usize; let start_idx = idx * bytes_per_value; let end_idx = (idx + 1) * bytes_per_value; @@ -156,7 +155,7 @@ impl Signal { // //(REMOVE THIS COMMENT)below is from self // // TODO : should this be usize? // desired_time: BigUint, - // ) -> Result { + // ) -> Result { // let signal_idx = match self { // Self::Data { // name, @@ -197,7 +196,7 @@ impl Signal { // scope_parent, // } => { // if num_bits.is_none() { - // return Err(LookupErrors::NoNumBits); + // return Err(SignalErrors::NoNumBits); // } // Ok(( // nums_encoded_as_fixed_width_le_u8, @@ -207,22 +206,22 @@ impl Signal { // name, // )) // } - // Signal::Alias { name, signal_alias } => Err(LookupErrors::PointsToAlias), + // Signal::Alias { name, signal_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_num_tmstmp_vals_on_tmln.is_empty() { - // return Err(LookupErrors::EmptyTimeline); + // return Err(SignalErrors::EmptyTimeline); // } // // assertion that value_sequence is a proper multiple of // // timeline_markers // let bytes_required = - // Signal::bytes_required(&num_bits, &name).map_err(|arg| LookupErrors::Other(arg))?; + // Signal::bytes_required(&num_bits, &name).map_err(|arg| SignalErrors::Other(arg))?; // if lsb_indxs_of_num_tmstmp_vals_on_tmln.len() // != (nums_encoded_as_fixed_width_le_u8.len() * bytes_required as usize) // { - // return Err(LookupErrors::TimelineNotMultiple); + // return Err(SignalErrors::TimelineNotMultiple); // } // // let TimelineIdx(desired_time) = desired_time; @@ -231,7 +230,7 @@ impl Signal { // // start of the timeline // let TimelineIdx(timeline_start_time) = timeline_cursors.first().unwrap(); // if desired_time < *timeline_start_time { - // return Err(LookupErrors::PreTimeline { + // return Err(SignalErrors::PreTimeline { // desired_time: TimelineIdx(desired_time), // timeline_start_time: TimelineIdx(*timeline_start_time), // }); @@ -286,7 +285,7 @@ impl Signal { // let ordered_left = left_time < desired_time; // let ordered_right = desired_time < right_time; // if !(ordered_left && ordered_right) { - // return Err(LookupErrors::OrderingFailure); + // return Err(SignalErrors::OrderingFailure); // } // let u8_timeline_start_idx = idx * bytes_per_value; -- 2.47.1 From 02e28f0357afe1cf77a95bb021cdf7db47847c5e Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Mon, 22 Aug 2022 10:14:26 -0400 Subject: [PATCH 7/9] more restrictive exports --- src/vcd.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vcd.rs b/src/vcd.rs index 5d228f8..b245601 100644 --- a/src/vcd.rs +++ b/src/vcd.rs @@ -2,13 +2,13 @@ mod reader; use reader::*; mod types; -pub(super) use types::*; +use types::*; mod parse; -pub(super) use parse::*; +pub use parse::*; mod signal; -pub(super) use signal::*; +use signal::*; mod utilities; use utilities::*; -- 2.47.1 From 223d36c1a6de9daa2d69cf0636ab592751fd156d Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Mon, 22 Aug 2022 11:14:53 -0400 Subject: [PATCH 8/9] successful integration of untested query timeline function --- src/vcd/signal.rs | 248 ++++++++++++++++++++-------------------------- 1 file changed, 107 insertions(+), 141 deletions(-) diff --git a/src/vcd/signal.rs b/src/vcd/signal.rs index c158601..b09fe3a 100644 --- a/src/vcd/signal.rs +++ b/src/vcd/signal.rs @@ -145,155 +145,121 @@ impl Signal { Ok((timestamp, signal_val)) } - // pub(super) fn query_num_val_on_tmln( - // &self, - // //(REMOVE THIS COMMENT)below is from self - // nums_encoded_as_fixed_width_le_u8: &Vec, - // lsb_indxs_of_num_tmstmp_vals_on_tmln: &Vec, - // tmstmps_encoded_as_u8s: &Vec, - // all_signals: &Vec, - // //(REMOVE THIS COMMENT)below is from self - // // TODO : should this be usize? - // desired_time: BigUint, - // ) -> Result { - // let signal_idx = match self { - // Self::Data { - // name, - // sig_type, - // signal_error, - // num_bits, - // self_idx, - // .. - // } => { - // let SignalIdx(idx) = self_idx; - // *idx - // } - // Self::Alias { name, signal_alias } => { - // let SignalIdx(idx) = signal_alias; - // *idx - // } - // }; + pub(super) fn query_num_val_on_tmln( + &self, + desired_time: BigUint, + tmstmps_encoded_as_u8s: &Vec, + all_signals: &Vec, + ) -> Result { + let signal_idx = match self { + Self::Data { self_idx, .. } => { + let SignalIdx(idx) = self_idx; + *idx + } + Self::Alias { + name: _, + signal_alias, + } => { + let SignalIdx(idx) = signal_alias; + *idx + } + }; - // let ( - // nums_encoded_as_fixed_width_le_u8, - // lsb_indxs_of_num_tmstmp_vals_on_tmln, - // tmstmps_encoded_as_u8s, - // num_bits, - // name, - // ) = match all_signals[signal_idx] { - // Signal::Data { - // name, - // sig_type, - // signal_error, - // num_bits, - // self_idx, - // ref nums_encoded_as_fixed_width_le_u8, - // string_vals, - // ref lsb_indxs_of_num_tmstmp_vals_on_tmln, - // byte_len_of_num_tmstmp_vals_on_tmln, - // lsb_indxs_of_string_tmstmp_vals_on_tmln, - // byte_len_of_string_tmstmp_vals_on_tmln, - // scope_parent, - // } => { - // if num_bits.is_none() { - // return Err(SignalErrors::NoNumBits); - // } - // Ok(( - // nums_encoded_as_fixed_width_le_u8, - // lsb_indxs_of_num_tmstmp_vals_on_tmln, - // tmstmps_encoded_as_u8s, - // num_bits, - // name, - // )) - // } - // Signal::Alias { name, signal_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_num_tmstmp_vals_on_tmln.is_empty() { - // return Err(SignalErrors::EmptyTimeline); - // } + let (nums_encoded_as_fixed_width_le_u8, lsb_indxs_of_num_tmstmp_vals_on_tmln, num_bytes) = + match &all_signals[signal_idx] { + Signal::Data { + num_bytes, + ref nums_encoded_as_fixed_width_le_u8, + ref lsb_indxs_of_num_tmstmp_vals_on_tmln, + .. + } => { + if num_bytes.is_none() { + return Err(SignalErrors::NoNumBytes); + } + Ok(( + nums_encoded_as_fixed_width_le_u8, + lsb_indxs_of_num_tmstmp_vals_on_tmln, + num_bytes, + )) + } + Signal::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_num_tmstmp_vals_on_tmln.is_empty() { + return Err(SignalErrors::EmptyTimeline); + } - // // assertion that value_sequence is a proper multiple of - // // timeline_markers - // let bytes_required = - // Signal::bytes_required(&num_bits, &name).map_err(|arg| SignalErrors::Other(arg))?; - // if lsb_indxs_of_num_tmstmp_vals_on_tmln.len() - // != (nums_encoded_as_fixed_width_le_u8.len() * bytes_required as usize) - // { - // return Err(SignalErrors::TimelineNotMultiple); - // } + // assertion that value_sequence is a proper multiple of + // timeline_markers + let bytes_required = num_bytes.ok_or_else(|| { + SignalErrors::Other(format!( + "Error near {}:{}. num_bytes empty.", + file!(), + line!() + )) + })?; + if lsb_indxs_of_num_tmstmp_vals_on_tmln.len() + != (nums_encoded_as_fixed_width_le_u8.len() * bytes_required as usize) + { + return Err(SignalErrors::TimelineNotMultiple); + } - // // let TimelineIdx(desired_time) = desired_time; + // check if we're requesting a value that occurs before the recorded + // start of the timeline + let (timeline_start_time, _) = self.lookup_time_and_val(0, tmstmps_encoded_as_u8s)?; + if desired_time < timeline_start_time { + return Err(SignalErrors::PreTimeline { + desired_time: desired_time, + timeline_start_time: timeline_start_time, + }); + } - // // check if we're requesting a value that occurs before the recorded - // // start of the timeline - // let TimelineIdx(timeline_start_time) = timeline_cursors.first().unwrap(); - // if desired_time < *timeline_start_time { - // return Err(SignalErrors::PreTimeline { - // desired_time: TimelineIdx(desired_time), - // timeline_start_time: TimelineIdx(*timeline_start_time), - // }); - // } + let mut lower_idx = 0usize; + let mut upper_idx = lsb_indxs_of_num_tmstmp_vals_on_tmln.len() - 1; + let (timeline_end_time, timeline_end_val) = + self.lookup_time_and_val(upper_idx, tmstmps_encoded_as_u8s)?; - // let mut lower_idx = 0usize; - // let mut upper_idx = timeline_cursors.len() - 1; + // check if we're requesting a value that occurs beyond the end of the timeline, + // if so, return the last value in this timeline + if desired_time > timeline_end_time { + return Ok(timeline_end_val); + } - // // check if we're requesting a value that occurs beyond the end of the timeline, - // // if so, return the last value in this timeline - // let TimelineIdx(timeline_end_time) = timeline_cursors.last().unwrap(); - // if desired_time > *timeline_end_time { - // let range = (value_sequence_as_bytes.len() - bytes_per_value)..; - // let value_by_bytes = &value_sequence_as_bytes[range]; - // let value = BigUint::from_bytes_le(value_by_bytes); + // This while loop is the meat of the lookup. Performance is log2(n), + // where n is the number of events on the timeline. + // We can assume that by the time we get here, that the desired_time + // is an event that occurs on the timeline, given that we handle any events + // occuring after or before the recorded tiimeline in the code above. + while lower_idx <= upper_idx { + let mid_idx = lower_idx + ((upper_idx - lower_idx) / 2); + let (curr_time, curr_val) = + self.lookup_time_and_val(mid_idx, tmstmps_encoded_as_u8s)?; + let ordering = curr_time.cmp(&desired_time); - // return Ok(value); - // } + match ordering { + std::cmp::Ordering::Less => { + lower_idx = mid_idx + 1; + } + std::cmp::Ordering::Equal => { + return Ok(curr_val); + } + std::cmp::Ordering::Greater => { + upper_idx = mid_idx - 1; + } + } + } - // // This while loop is the meat of the lookup. Performance is log2(n), - // // where n is the number of events on the timeline. - // // We can assume that by the time we get here, that the desired_time - // // is an event that occurs on the timeline, given that we handle any events - // // occuring after or before the recorded tiimeline in the code above. - // while lower_idx <= upper_idx { - // let mid_idx = lower_idx + ((upper_idx - lower_idx) / 2); - // let TimelineIdx(curr_time) = timeline_cursors[mid_idx]; - // let ordering = curr_time.cmp(&desired_time); + let (left_time, left_val) = + self.lookup_time_and_val(lower_idx - 1, tmstmps_encoded_as_u8s)?; + let (right_time, _) = self.lookup_time_and_val(lower_idx - 1, tmstmps_encoded_as_u8s)?; - // match ordering { - // std::cmp::Ordering::Less => { - // lower_idx = mid_idx + 1; - // } - // std::cmp::Ordering::Equal => { - // let u8_timeline_start_idx = mid_idx * bytes_per_value; - // let u8_timeline_end_idx = u8_timeline_start_idx + bytes_per_value; - // let range = u8_timeline_start_idx..u8_timeline_end_idx; - // let value_by_bytes = &value_sequence_as_bytes[range]; - // let value = BigUint::from_bytes_le(value_by_bytes); - // return Ok(value); - // } - // std::cmp::Ordering::Greater => { - // upper_idx = mid_idx - 1; - // } - // } - // } + let ordered_left = left_time < desired_time; + let ordered_right = desired_time < right_time; + if !(ordered_left && ordered_right) { + return Err(SignalErrors::OrderingFailure); + } - // let idx = lower_idx - 1; - // let TimelineIdx(left_time) = timeline_cursors[idx]; - // let TimelineIdx(right_time) = timeline_cursors[idx + 1]; - - // let ordered_left = left_time < desired_time; - // let ordered_right = desired_time < right_time; - // if !(ordered_left && ordered_right) { - // return Err(SignalErrors::OrderingFailure); - // } - - // let u8_timeline_start_idx = idx * bytes_per_value; - // let u8_timeline_end_idx = u8_timeline_start_idx + bytes_per_value; - // let range = u8_timeline_start_idx..u8_timeline_end_idx; - // let value_by_bytes = &value_sequence_as_bytes[range]; - // let value = BigUint::from_bytes_le(value_by_bytes); - - // return Ok(value); - // } + return Ok(left_val); + } } -- 2.47.1 From aeb796c46b1cf597a988afdc319524bb9e0bda17 Mon Sep 17 00:00:00 2001 From: Yehowshua Immanuel Date: Fri, 2 Sep 2022 15:05:33 -0400 Subject: [PATCH 9/9] ordered search now working --- src/vcd/parse.rs | 14 +++++++ src/vcd/parse/events.rs | 85 ++++++++++++++++++++++++++++++----------- src/vcd/parse/scopes.rs | 2 +- src/vcd/signal.rs | 40 ++++++++++++------- 4 files changed, 103 insertions(+), 38 deletions(-) diff --git a/src/vcd/parse.rs b/src/vcd/parse.rs index e3771d9..5260604 100644 --- a/src/vcd/parse.rs +++ b/src/vcd/parse.rs @@ -39,6 +39,20 @@ pub fn parse_vcd(file: File) -> Result { parse_scopes(&mut word_gen, &mut vcd, &mut signal_map)?; parse_events(&mut word_gen, &mut vcd, &mut signal_map)?; + let signal = vcd.try_dereference_alias(signal_map.get("Q").unwrap())?; + let name = match signal { + Signal::Data { name, .. } => name, + _ => "ERROR", + }; + let val = signal + .query_num_val_on_tmln( + BigUint::from(4687u32), + &vcd.tmstmps_encoded_as_u8s, + &vcd.all_signals, + ) + .unwrap(); + dbg!(format!("{val:#X}")); + dbg!(name); Ok(vcd) } diff --git a/src/vcd/parse/events.rs b/src/vcd/parse/events.rs index 8e3d18b..053a22b 100644 --- a/src/vcd/parse/events.rs +++ b/src/vcd/parse/events.rs @@ -1,3 +1,5 @@ +use num::Zero; + use super::*; pub(super) fn parse_events<'a>( @@ -7,6 +9,7 @@ pub(super) fn parse_events<'a>( ) -> Result<(), String> { let mut curr_tmstmp_lsb_idx = 0u32; let mut curr_tmstmp_len_u8 = 0u8; + let mut curr_time = BigUint::zero(); loop { let next_word = word_reader.next_word(); @@ -35,6 +38,7 @@ pub(super) fn parse_events<'a>( "Error near {f}:{l}. Failed to parse {value} as BigInt at {cursor:?}" ) })?; + curr_time = value.clone(); let mut value = value.to_bytes_le(); // TODO : u32 helps with less memory, but should ideally likely be // configurable. @@ -45,16 +49,15 @@ pub(super) fn parse_events<'a>( line!() ) })?; - vcd.tmstmps_encoded_as_u8s.append(&mut value); curr_tmstmp_lsb_idx = u32::try_from(vcd.tmstmps_encoded_as_u8s.len()).map_err(|_| { format!( - "Error near {}:{}. Failed to convert from usize to u8.", + "Error near {}:{}. Failed to convert from usize to u32.", file!(), line!() ) })?; - // curr_tmstmp_lsb_idx = vcd.tmstmps_encoded_as_u8s.len(); + vcd.tmstmps_encoded_as_u8s.append(&mut value); } // handle the case of an n bit signal whose value must be parsed @@ -111,10 +114,6 @@ pub(super) fn parse_events<'a>( let signal = vcd.try_dereference_alias_mut(signal_idx)?; - // we may have to dereference a signal if it's pointing at an alias - // let signal = &vcd.all_signals[*signal_idx]; - // let signal = signal.try_dereference_alias_mut(&vcd.all_signals)?; - match signal { Signal::Data { name, @@ -172,6 +171,19 @@ pub(super) fn parse_events<'a>( string_vals.push(value_string); Ok(()) } else { + // timestamp stuff + lsb_indxs_of_num_tmstmp_vals_on_tmln + .push(LsbIdxOfTmstmpValOnTmln(curr_tmstmp_lsb_idx)); + byte_len_of_num_tmstmp_vals_on_tmln.push(curr_tmstmp_len_u8); + + // value stuff + // we may need to zero extend values + // so that we end up storing all values + // of a particular signal in a consistent + // amount of bytes + let bytes_required = num_bytes.ok_or_else(|| { + format!("Error near {}:{}. num_bytes empty.", file!(), line!()) + })?; let mut curr_num_bytes = u8::try_from(value_u8.len()).map_err(|_| { format!( @@ -182,22 +194,12 @@ pub(super) fn parse_events<'a>( line!() ) })?; - lsb_indxs_of_num_tmstmp_vals_on_tmln - .push(LsbIdxOfTmstmpValOnTmln(curr_tmstmp_lsb_idx)); - - // we may need to zero extend values - // so that we end up storing all values - // of a particular signal in a consistent - // amount of bytes - let bytes_required = num_bytes.ok_or_else(|| { - format!("Error near {}:{}. num_bytes empty.", file!(), line!()) - })?; + nums_encoded_as_fixed_width_le_u8.append(&mut value_u8); while curr_num_bytes < bytes_required { nums_encoded_as_fixed_width_le_u8.push(0u8); curr_num_bytes += 1; } - byte_len_of_num_tmstmp_vals_on_tmln.push(curr_tmstmp_len_u8); Ok(()) } } @@ -231,6 +233,7 @@ pub(super) fn parse_events<'a>( sig_type, ref mut signal_error, num_bits, + num_bytes, nums_encoded_as_fixed_width_le_u8, lsb_indxs_of_num_tmstmp_vals_on_tmln, byte_len_of_num_tmstmp_vals_on_tmln, @@ -271,10 +274,25 @@ pub(super) fn parse_events<'a>( Err(msg)?; } }; - nums_encoded_as_fixed_width_le_u8.push(0u8); + // timestamp stuff lsb_indxs_of_num_tmstmp_vals_on_tmln .push(LsbIdxOfTmstmpValOnTmln(curr_tmstmp_lsb_idx)); byte_len_of_num_tmstmp_vals_on_tmln.push(curr_tmstmp_len_u8); + + // value stuff + // we may need to zero extend values + // so that we end up storing all values + // of a particular signal in a consistent + // amount of bytes + let bytes_required = num_bytes.ok_or_else(|| { + format!("Error near {}:{}. num_bytes empty.", file!(), line!()) + })?; + nums_encoded_as_fixed_width_le_u8.push(0u8); + let mut curr_num_bytes = 1; + while curr_num_bytes < bytes_required { + nums_encoded_as_fixed_width_le_u8.push(0u8); + curr_num_bytes += 1; + } Ok(()) } Signal::Alias { .. } => { @@ -306,6 +324,7 @@ pub(super) fn parse_events<'a>( sig_type, ref mut signal_error, num_bits, + num_bytes, nums_encoded_as_fixed_width_le_u8, lsb_indxs_of_num_tmstmp_vals_on_tmln, byte_len_of_num_tmstmp_vals_on_tmln, @@ -346,10 +365,25 @@ pub(super) fn parse_events<'a>( Err(msg)?; } }; - nums_encoded_as_fixed_width_le_u8.push(1u8); + // timestamp stuff lsb_indxs_of_num_tmstmp_vals_on_tmln .push(LsbIdxOfTmstmpValOnTmln(curr_tmstmp_lsb_idx)); byte_len_of_num_tmstmp_vals_on_tmln.push(curr_tmstmp_len_u8); + + // value stuff + // we may need to zero extend values + // so that we end up storing all values + // of a particular signal in a consistent + // amount of bytes + let bytes_required = num_bytes.ok_or_else(|| { + format!("Error near {}:{}. num_bytes empty.", file!(), line!()) + })?; + nums_encoded_as_fixed_width_le_u8.push(1u8); + let mut curr_num_bytes = 1; + while curr_num_bytes < bytes_required { + nums_encoded_as_fixed_width_le_u8.push(0u8); + curr_num_bytes += 1; + } Ok(()) } Signal::Alias { .. } => { @@ -362,7 +396,7 @@ pub(super) fn parse_events<'a>( }?; } - // other one bit cases + // // other one bit cases "x" | "X" | "z" | "Z" | "u" | "U" => { let val = word.to_string(); // lokup signal idx @@ -385,6 +419,7 @@ pub(super) fn parse_events<'a>( num_bits, string_vals, byte_len_of_num_tmstmp_vals_on_tmln, + byte_len_of_string_tmstmp_vals_on_tmln, lsb_indxs_of_string_tmstmp_vals_on_tmln, .. } => { @@ -423,10 +458,14 @@ pub(super) fn parse_events<'a>( Err(msg)?; } }; - string_vals.push(val); + + // record timestamp at which this event occurs lsb_indxs_of_string_tmstmp_vals_on_tmln .push(LsbIdxOfTmstmpValOnTmln(curr_tmstmp_lsb_idx)); - byte_len_of_num_tmstmp_vals_on_tmln.push(curr_tmstmp_len_u8); + byte_len_of_string_tmstmp_vals_on_tmln.push(curr_tmstmp_len_u8); + + // record value + string_vals.push(val); Ok(()) } Signal::Alias { .. } => { diff --git a/src/vcd/parse/scopes.rs b/src/vcd/parse/scopes.rs index a4cfc07..c48888c 100644 --- a/src/vcd/parse/scopes.rs +++ b/src/vcd/parse/scopes.rs @@ -122,8 +122,8 @@ pub(super) fn parse_var<'a>( string_vals: vec![], lsb_indxs_of_num_tmstmp_vals_on_tmln: vec![], byte_len_of_num_tmstmp_vals_on_tmln: vec![], - lsb_indxs_of_string_tmstmp_vals_on_tmln: vec![], byte_len_of_string_tmstmp_vals_on_tmln: vec![], + lsb_indxs_of_string_tmstmp_vals_on_tmln: vec![], scope_parent: parent_scope_idx, }; (signal, signal_idx) diff --git a/src/vcd/signal.rs b/src/vcd/signal.rs index b09fe3a..5582182 100644 --- a/src/vcd/signal.rs +++ b/src/vcd/signal.rs @@ -58,8 +58,8 @@ pub(super) enum Signal { // a particular timestamp is composed of. lsb_indxs_of_num_tmstmp_vals_on_tmln: Vec, byte_len_of_num_tmstmp_vals_on_tmln: Vec, - lsb_indxs_of_string_tmstmp_vals_on_tmln: Vec, byte_len_of_string_tmstmp_vals_on_tmln: Vec, + lsb_indxs_of_string_tmstmp_vals_on_tmln: Vec, scope_parent: ScopeIdx, }, Alias { @@ -76,9 +76,12 @@ pub(super) enum SignalErrors { }, EmptyTimeline, TimelineNotMultiple, - OrderingFailure, + OrderingFailure { + lhs_time: BigUint, + mid_time: BigUint, + rhs_time: BigUint, + }, PointsToAlias, - NoNumBits, NoNumBytes, Other(String), } @@ -100,9 +103,9 @@ impl Signal { })?; Ok(bytes_required) } - pub fn lookup_time_and_val( + pub(super) fn lookup_time_and_val( &self, - idx: usize, + event_idx: usize, tmstmps_encoded_as_u8s: &Vec, ) -> Result<(TimeStamp, SignalValNum), SignalErrors> { let ( @@ -127,25 +130,26 @@ impl Signal { }?; // get index - let LsbIdxOfTmstmpValOnTmln(timestamp_idx) = lsb_indxs_of_num_tmstmp_vals_on_tmln[idx]; + let LsbIdxOfTmstmpValOnTmln(timestamp_idx) = + lsb_indxs_of_num_tmstmp_vals_on_tmln[event_idx]; let timestamp_idx = timestamp_idx as usize; // form timestamp - let byte_len = byte_len_of_num_tmstmp_vals_on_tmln[timestamp_idx] as usize; + let byte_len = byte_len_of_num_tmstmp_vals_on_tmln[event_idx] as usize; let timestamp = &tmstmps_encoded_as_u8s[timestamp_idx..(timestamp_idx + byte_len)]; let timestamp = BigUint::from_bytes_le(timestamp); // get signal value let bytes_per_value = num_bytes.ok_or_else(|| SignalErrors::NoNumBytes)?; let bytes_per_value = bytes_per_value as usize; - let start_idx = idx * bytes_per_value; - let end_idx = (idx + 1) * bytes_per_value; + let start_idx = event_idx * bytes_per_value; + let end_idx = (event_idx + 1) * bytes_per_value; let signal_val = &nums_encoded_as_fixed_width_le_u8[start_idx..end_idx]; let signal_val = BigUint::from_bytes_le(signal_val); Ok((timestamp, signal_val)) } - pub(super) fn query_num_val_on_tmln( + pub fn query_num_val_on_tmln( &self, desired_time: BigUint, tmstmps_encoded_as_u8s: &Vec, @@ -199,9 +203,13 @@ impl Signal { line!() )) })?; - if lsb_indxs_of_num_tmstmp_vals_on_tmln.len() - != (nums_encoded_as_fixed_width_le_u8.len() * bytes_required as usize) + if nums_encoded_as_fixed_width_le_u8.len() + != (lsb_indxs_of_num_tmstmp_vals_on_tmln.len() * (bytes_required as usize)) { + dbg!(( + nums_encoded_as_fixed_width_le_u8.len(), + (lsb_indxs_of_num_tmstmp_vals_on_tmln.len() * (bytes_required as usize)) + )); return Err(SignalErrors::TimelineNotMultiple); } @@ -252,12 +260,16 @@ impl Signal { let (left_time, left_val) = self.lookup_time_and_val(lower_idx - 1, tmstmps_encoded_as_u8s)?; - let (right_time, _) = self.lookup_time_and_val(lower_idx - 1, tmstmps_encoded_as_u8s)?; + let (right_time, _) = self.lookup_time_and_val(lower_idx, tmstmps_encoded_as_u8s)?; let ordered_left = left_time < desired_time; let ordered_right = desired_time < right_time; if !(ordered_left && ordered_right) { - return Err(SignalErrors::OrderingFailure); + return Err(SignalErrors::OrderingFailure { + lhs_time: left_time, + mid_time: desired_time, + rhs_time: right_time, + }); } return Ok(left_val); -- 2.47.1