support for strings seems to work
This commit is contained in:
parent
cd6ea71b8d
commit
5700db83a0
|
@ -75,7 +75,7 @@ Here's a command to test on a malformed VCD:
|
||||||
- [ ] may need to refactor with allow for get_mut for dynamic
|
- [ ] may need to refactor with allow for get_mut for dynamic
|
||||||
compression-decompression for multiple signal structs
|
compression-decompression for multiple signal structs
|
||||||
at once to allow for multi-threading
|
at once to allow for multi-threading
|
||||||
- [ ] add string support for timeline value scanner
|
- [x] add string support for timeline value scanner
|
||||||
- [ ] test against large waveforms from the
|
- [ ] test against large waveforms from the
|
||||||
[verilog-vcd-parser](https://github.com/ben-marshall/verilog-vcd-parser)
|
[verilog-vcd-parser](https://github.com/ben-marshall/verilog-vcd-parser)
|
||||||
tool
|
tool
|
||||||
|
@ -91,6 +91,7 @@ Here's a command to test on a malformed VCD:
|
||||||
- [ ] Move part of the performance section to another markdown file.
|
- [ ] Move part of the performance section to another markdown file.
|
||||||
|
|
||||||
## Repairs
|
## Repairs
|
||||||
|
- [ ] replace str bracket indices with get(slice)
|
||||||
- [ ] make a custom date parser for possibly up to 18 different versions(that is, for each possible tool).
|
- [ ] make a custom date parser for possibly up to 18 different versions(that is, for each possible tool).
|
||||||
- [ ] Consolidate error messages and add cursors throughout.
|
- [ ] Consolidate error messages and add cursors throughout.
|
||||||
- [ ] Add file and line to the enum errors.
|
- [ ] Add file and line to the enum errors.
|
||||||
|
@ -98,6 +99,7 @@ Here's a command to test on a malformed VCD:
|
||||||
able to successfully parse all sample VCDs.
|
able to successfully parse all sample VCDs.
|
||||||
|
|
||||||
## Code Consistency
|
## Code Consistency
|
||||||
|
- [ ] split impls in signal.rs into groups
|
||||||
- [ ] Change error messages to line and filenames. Go through all calls to unwrap.
|
- [ ] Change error messages to line and filenames. Go through all calls to unwrap.
|
||||||
- [ ] search for any unwraps or any direct vectors indexing
|
- [ ] search for any unwraps or any direct vectors indexing
|
||||||
- [ ] Handle TODOs
|
- [ ] Handle TODOs
|
||||||
|
|
42
src/main.rs
42
src/main.rs
|
@ -6,7 +6,7 @@ pub mod test;
|
||||||
pub mod vcd;
|
pub mod vcd;
|
||||||
use vcd::*;
|
use vcd::*;
|
||||||
|
|
||||||
use num::BigUint;
|
use num::{BigUint, traits::sign};
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
struct Cli {
|
struct Cli {
|
||||||
|
@ -19,32 +19,48 @@ fn main() -> std::io::Result<()> {
|
||||||
let args = Cli::parse();
|
let args = Cli::parse();
|
||||||
|
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
let now = Instant::now();
|
|
||||||
|
|
||||||
|
let now = Instant::now();
|
||||||
let file = File::open(&args.path)?;
|
let file = File::open(&args.path)?;
|
||||||
let vcd = parse_vcd(file).unwrap();
|
let vcd = parse_vcd(file).unwrap();
|
||||||
|
|
||||||
let elapsed = now.elapsed();
|
let elapsed = now.elapsed();
|
||||||
println!("Elapsed: {:.2?}", elapsed);
|
|
||||||
|
println!("Parsed VCD file {} : {:.2?}", &args.path.as_os_str().to_str().unwrap(), elapsed);
|
||||||
|
|
||||||
// the following is really only for test-vcd-files/icarus/CPU.vcd
|
// the following is really only for test-vcd-files/icarus/CPU.vcd
|
||||||
// at the moment
|
// at the moment
|
||||||
if args.path.as_os_str().to_str().unwrap() == "test-vcd-files/icarus/CPU.vcd" {
|
if args.path.as_os_str().to_str().unwrap() == "test-vcd-files/icarus/CPU.vcd" {
|
||||||
let signal = &vcd.all_signals[51];
|
let rs2_data_signal = &vcd.all_signals[51];
|
||||||
let name = match signal {
|
let name = rs2_data_signal.name();
|
||||||
Signal::Data { name, .. } => name,
|
// query testbench -> CPU -> rs2_data[31:0] @ 4687s
|
||||||
_ => "ERROR",
|
let time = BigUint::from(4687u32);
|
||||||
};
|
let val = rs2_data_signal
|
||||||
let val = signal
|
|
||||||
.query_num_val_on_tmln(
|
.query_num_val_on_tmln(
|
||||||
BigUint::from(4687u32),
|
&time,
|
||||||
&vcd.tmstmps_encoded_as_u8s,
|
&vcd.tmstmps_encoded_as_u8s,
|
||||||
&vcd.all_signals,
|
&vcd.all_signals,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
dbg!(format!("{val:#X}"));
|
println!("Signal `{name}` has value `{val}` at time `{time}`");
|
||||||
dbg!(name);
|
|
||||||
|
// also need to test testbench -> CPU -> ID_EX_RD[4:0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this is to help with testing stringed enums
|
||||||
|
if args.path.as_os_str().to_str().unwrap() == "test-vcd-files/amaranth/up_counter.vcd" {
|
||||||
|
let state_signal = &vcd.all_signals[4];
|
||||||
|
let name = state_signal.name();
|
||||||
|
let time = BigUint::from(57760000u32);
|
||||||
|
let val = state_signal
|
||||||
|
.query_string_val_on_tmln(
|
||||||
|
&time,
|
||||||
|
&vcd.tmstmps_encoded_as_u8s,
|
||||||
|
&vcd.all_signals,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
println!("Signal `{name}` has value `{val}` at time `{time}`");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,7 +112,7 @@ pub(super) fn parse_events<'a>(
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let signal = vcd.try_dereference_alias_mut(signal_idx)?;
|
let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?;
|
||||||
|
|
||||||
match signal {
|
match signal {
|
||||||
Signal::Data {
|
Signal::Data {
|
||||||
|
@ -225,7 +225,7 @@ pub(super) fn parse_events<'a>(
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let signal = vcd.try_dereference_alias_mut(signal_idx)?;
|
let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?;
|
||||||
|
|
||||||
match signal {
|
match signal {
|
||||||
Signal::Data {
|
Signal::Data {
|
||||||
|
@ -316,7 +316,7 @@ pub(super) fn parse_events<'a>(
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let signal = vcd.try_dereference_alias_mut(signal_idx)?;
|
let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?;
|
||||||
|
|
||||||
match signal {
|
match signal {
|
||||||
Signal::Data {
|
Signal::Data {
|
||||||
|
@ -409,7 +409,7 @@ pub(super) fn parse_events<'a>(
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let signal = vcd.try_dereference_alias_mut(signal_idx)?;
|
let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?;
|
||||||
|
|
||||||
match signal {
|
match signal {
|
||||||
Signal::Data {
|
Signal::Data {
|
||||||
|
@ -477,6 +477,55 @@ pub(super) fn parse_events<'a>(
|
||||||
}
|
}
|
||||||
}?;
|
}?;
|
||||||
}
|
}
|
||||||
|
"s" => {
|
||||||
|
let val = word[1..].to_string();
|
||||||
|
let (hash, cursor) = next_word!(word_reader)?;
|
||||||
|
// lokup signal idx
|
||||||
|
let signal_idx = signal_map.get(hash).ok_or(()).map_err(|_| {
|
||||||
|
format!(
|
||||||
|
"Error near {}:{}. Failed to lookup signal {hash} at {cursor:?}",
|
||||||
|
file!(),
|
||||||
|
line!()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let signal = vcd.dealiasing_signal_idx_to_signal_lookup_mut(signal_idx)?;
|
||||||
|
|
||||||
|
match signal {
|
||||||
|
Signal::Data {
|
||||||
|
name,
|
||||||
|
sig_type,
|
||||||
|
ref mut signal_error,
|
||||||
|
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,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
// if this is a bad signal, go ahead and skip it
|
||||||
|
if signal_error.is_some() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// record timestamp at which this event occurs
|
||||||
|
lsb_indxs_of_string_tmstmp_vals_on_tmln
|
||||||
|
.push(LsbIdxOfTmstmpValOnTmln(curr_tmstmp_lsb_idx));
|
||||||
|
byte_len_of_string_tmstmp_vals_on_tmln.push(curr_tmstmp_len_u8);
|
||||||
|
|
||||||
|
// record string value
|
||||||
|
string_vals.push(val);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Signal::Alias { .. } => {
|
||||||
|
let (f, l) = (file!(), line!());
|
||||||
|
let msg = format!(
|
||||||
|
"Error near {f}:{l}, a signal alias should not point to a signal alias.\n\
|
||||||
|
This error occurred while parsing vcd file at {cursor:?}");
|
||||||
|
Err(msg)
|
||||||
|
}
|
||||||
|
}?;
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,7 @@ pub enum SignalErrors {
|
||||||
},
|
},
|
||||||
EmptyTimeline,
|
EmptyTimeline,
|
||||||
TimelineNotMultiple,
|
TimelineNotMultiple,
|
||||||
|
StrTmlnLenMismatch,
|
||||||
OrderingFailure {
|
OrderingFailure {
|
||||||
lhs_time: BigUint,
|
lhs_time: BigUint,
|
||||||
mid_time: BigUint,
|
mid_time: BigUint,
|
||||||
|
@ -90,6 +91,29 @@ pub enum SignalErrors {
|
||||||
type TimeStamp = BigUint;
|
type TimeStamp = BigUint;
|
||||||
type SignalValNum = BigUint;
|
type SignalValNum = BigUint;
|
||||||
|
|
||||||
|
// getter functions
|
||||||
|
impl Signal {
|
||||||
|
pub fn self_idx(&self) -> Result<SignalIdx, String> {
|
||||||
|
match self {
|
||||||
|
Signal::Data { self_idx, ..} => {return Ok(self_idx.clone())},
|
||||||
|
Signal::Alias { .. } => Err(format!(
|
||||||
|
"Error near {}:{}. A signal alias shouldn't \
|
||||||
|
point to a signal alias.",
|
||||||
|
file!(),
|
||||||
|
line!()
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Signal::Data { name, ..} => name,
|
||||||
|
Signal::Alias { name, .. } => name
|
||||||
|
}.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
impl Signal {
|
impl Signal {
|
||||||
pub(super) fn bytes_required(num_bits: u16, name: &String) -> Result<u8, String> {
|
pub(super) fn bytes_required(num_bits: u16, name: &String) -> Result<u8, String> {
|
||||||
let bytes_required = (num_bits / 8) + if (num_bits % 8) > 0 { 1 } else { 0 };
|
let bytes_required = (num_bits / 8) + if (num_bits % 8) > 0 { 1 } else { 0 };
|
||||||
|
@ -187,9 +211,124 @@ impl Signal {
|
||||||
|
|
||||||
Ok((timestamp, signal_val))
|
Ok((timestamp, signal_val))
|
||||||
}
|
}
|
||||||
|
pub fn query_string_val_on_tmln(
|
||||||
|
&self,
|
||||||
|
desired_time: &BigUint,
|
||||||
|
tmstmps_encoded_as_u8s: &Vec<u8>,
|
||||||
|
all_signals: &Vec<Signal>,
|
||||||
|
) -> Result<String, SignalErrors> {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// if the signal idx points to data variant of the signal,
|
||||||
|
// extract:
|
||||||
|
// 1. the vector of string values
|
||||||
|
// 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] {
|
||||||
|
Signal::Data {
|
||||||
|
ref string_vals,
|
||||||
|
ref lsb_indxs_of_string_tmstmp_vals_on_tmln,
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
Ok((
|
||||||
|
string_vals,
|
||||||
|
lsb_indxs_of_string_tmstmp_vals_on_tmln,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
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_string_tmstmp_vals_on_tmln.is_empty() {
|
||||||
|
return Err(SignalErrors::EmptyTimeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the vector of string timeline lsb indices should have the same
|
||||||
|
// length as the vector of string values
|
||||||
|
if string_vals.len() != lsb_indxs_of_string_tmstmp_vals_on_tmln.len() {
|
||||||
|
return Err(SignalErrors::StrTmlnLenMismatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if we're requesting a value that occurs before the recorded
|
||||||
|
// start of the timeline
|
||||||
|
let (timeline_start_time, _) =
|
||||||
|
self.time_and_str_val_at_event_idx(0, tmstmps_encoded_as_u8s)?;
|
||||||
|
if *desired_time < timeline_start_time {
|
||||||
|
return Err(SignalErrors::PreTimeline {
|
||||||
|
desired_time: desired_time.clone(),
|
||||||
|
timeline_start_time: timeline_start_time,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut lower_idx = 0usize;
|
||||||
|
let mut upper_idx = lsb_indxs_of_string_tmstmp_vals_on_tmln.len() - 1;
|
||||||
|
let (timeline_end_time, timeline_end_val) =
|
||||||
|
self.time_and_str_val_at_event_idx(upper_idx, tmstmps_encoded_as_u8s)?;
|
||||||
|
|
||||||
|
// 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.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.time_and_str_val_at_event_idx(mid_idx, tmstmps_encoded_as_u8s)?;
|
||||||
|
let ordering = curr_time.cmp(desired_time);
|
||||||
|
|
||||||
|
match ordering {
|
||||||
|
std::cmp::Ordering::Less => {
|
||||||
|
lower_idx = mid_idx + 1;
|
||||||
|
}
|
||||||
|
std::cmp::Ordering::Equal => {
|
||||||
|
return Ok(curr_val.to_string());
|
||||||
|
}
|
||||||
|
std::cmp::Ordering::Greater => {
|
||||||
|
upper_idx = mid_idx - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let (left_time, left_val) =
|
||||||
|
self.time_and_str_val_at_event_idx(lower_idx - 1, tmstmps_encoded_as_u8s)?;
|
||||||
|
let (right_time, _) =
|
||||||
|
self.time_and_str_val_at_event_idx(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 {
|
||||||
|
lhs_time: left_time,
|
||||||
|
mid_time: desired_time.clone(),
|
||||||
|
rhs_time: right_time,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(left_val.to_string());
|
||||||
|
}
|
||||||
pub fn query_num_val_on_tmln(
|
pub fn query_num_val_on_tmln(
|
||||||
&self,
|
&self,
|
||||||
desired_time: BigUint,
|
desired_time: &BigUint,
|
||||||
tmstmps_encoded_as_u8s: &Vec<u8>,
|
tmstmps_encoded_as_u8s: &Vec<u8>,
|
||||||
all_signals: &Vec<Signal>,
|
all_signals: &Vec<Signal>,
|
||||||
) -> Result<BigUint, SignalErrors> {
|
) -> Result<BigUint, SignalErrors> {
|
||||||
|
@ -207,6 +346,13 @@ impl Signal {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// if the signal idx points to data variant of the signal,
|
||||||
|
// extract:
|
||||||
|
// 1. the vector of LE u8 compressed values
|
||||||
|
// 2. the vector of indices into timeline where events occur
|
||||||
|
// for this signal
|
||||||
|
// 3. the number of bytes per value for this signal
|
||||||
|
// else we propagate Err(..).
|
||||||
let (nums_encoded_as_fixed_width_le_u8, lsb_indxs_of_num_tmstmp_vals_on_tmln, num_bytes) =
|
let (nums_encoded_as_fixed_width_le_u8, lsb_indxs_of_num_tmstmp_vals_on_tmln, num_bytes) =
|
||||||
match &all_signals[signal_idx] {
|
match &all_signals[signal_idx] {
|
||||||
Signal::Data {
|
Signal::Data {
|
||||||
|
@ -244,10 +390,6 @@ impl Signal {
|
||||||
if nums_encoded_as_fixed_width_le_u8.len()
|
if nums_encoded_as_fixed_width_le_u8.len()
|
||||||
!= (lsb_indxs_of_num_tmstmp_vals_on_tmln.len() * (bytes_required as usize))
|
!= (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);
|
return Err(SignalErrors::TimelineNotMultiple);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,9 +397,9 @@ impl Signal {
|
||||||
// start of the timeline
|
// start of the timeline
|
||||||
let (timeline_start_time, _) =
|
let (timeline_start_time, _) =
|
||||||
self.time_and_num_val_at_event_idx(0, tmstmps_encoded_as_u8s)?;
|
self.time_and_num_val_at_event_idx(0, tmstmps_encoded_as_u8s)?;
|
||||||
if desired_time < timeline_start_time {
|
if *desired_time < timeline_start_time {
|
||||||
return Err(SignalErrors::PreTimeline {
|
return Err(SignalErrors::PreTimeline {
|
||||||
desired_time: desired_time,
|
desired_time: desired_time.clone(),
|
||||||
timeline_start_time: timeline_start_time,
|
timeline_start_time: timeline_start_time,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -269,7 +411,7 @@ impl Signal {
|
||||||
|
|
||||||
// check if we're requesting a value that occurs beyond the end of the timeline,
|
// 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 so, return the last value in this timeline
|
||||||
if desired_time > timeline_end_time {
|
if *desired_time > timeline_end_time {
|
||||||
return Ok(timeline_end_val);
|
return Ok(timeline_end_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +424,7 @@ impl Signal {
|
||||||
let mid_idx = lower_idx + ((upper_idx - lower_idx) / 2);
|
let mid_idx = lower_idx + ((upper_idx - lower_idx) / 2);
|
||||||
let (curr_time, curr_val) =
|
let (curr_time, curr_val) =
|
||||||
self.time_and_num_val_at_event_idx(mid_idx, tmstmps_encoded_as_u8s)?;
|
self.time_and_num_val_at_event_idx(mid_idx, tmstmps_encoded_as_u8s)?;
|
||||||
let ordering = curr_time.cmp(&desired_time);
|
let ordering = curr_time.cmp(desired_time);
|
||||||
|
|
||||||
match ordering {
|
match ordering {
|
||||||
std::cmp::Ordering::Less => {
|
std::cmp::Ordering::Less => {
|
||||||
|
@ -302,12 +444,12 @@ impl Signal {
|
||||||
let (right_time, _) =
|
let (right_time, _) =
|
||||||
self.time_and_num_val_at_event_idx(lower_idx, tmstmps_encoded_as_u8s)?;
|
self.time_and_num_val_at_event_idx(lower_idx, tmstmps_encoded_as_u8s)?;
|
||||||
|
|
||||||
let ordered_left = left_time < desired_time;
|
let ordered_left = left_time < *desired_time;
|
||||||
let ordered_right = desired_time < right_time;
|
let ordered_right = *desired_time < right_time;
|
||||||
if !(ordered_left && ordered_right) {
|
if !(ordered_left && ordered_right) {
|
||||||
return Err(SignalErrors::OrderingFailure {
|
return Err(SignalErrors::OrderingFailure {
|
||||||
lhs_time: left_time,
|
lhs_time: left_time,
|
||||||
mid_time: desired_time,
|
mid_time: desired_time.clone(),
|
||||||
rhs_time: right_time,
|
rhs_time: right_time,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,12 +60,12 @@ pub struct VCD {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VCD {
|
impl VCD {
|
||||||
/// We take in a Signal and attempt to dereference that signal if it is of
|
/// We take in a Signal and attempt to de-alias that signal if it is of
|
||||||
/// variant ``Signal::Alias``. If it is of variant ``Signal::Alias`` and points to
|
/// variant ``Signal::Alias``. If it is of variant ``Signal::Alias`` and points to
|
||||||
/// another alias, that's an error. Otherwise, we return the ``Signal::Data``
|
/// another alias, that's an error. Otherwise, we return the ``Signal::Data``
|
||||||
/// pointed to by the ``Signal::Alias``.
|
/// pointed to by the ``Signal::Alias``.
|
||||||
/// If the Signal is of varint ``Signal::Data``, then that can be returned directly.
|
/// If the Signal is of varint ``Signal::Data``, then that can be returned directly.
|
||||||
pub(super) fn try_dereference_alias_mut<'a>(
|
pub(super) fn dealiasing_signal_idx_to_signal_lookup_mut<'a>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
idx: &SignalIdx,
|
idx: &SignalIdx,
|
||||||
) -> Result<&'a mut Signal, String> {
|
) -> Result<&'a mut Signal, String> {
|
||||||
|
@ -92,7 +92,7 @@ impl VCD {
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub(super) fn try_dereference_alias<'a>(
|
pub(super) fn dealiasing_signal_idx_to_signal_lookup<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
idx: &SignalIdx,
|
idx: &SignalIdx,
|
||||||
) -> Result<&'a Signal, String> {
|
) -> Result<&'a Signal, String> {
|
||||||
|
@ -106,6 +106,35 @@ impl VCD {
|
||||||
Signal::Alias { name, signal_alias } => *signal_alias,
|
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!()
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// Takes a signal as input and returns the signal if the signal is of the
|
||||||
|
/// Signal::Data variant, else the function follows follows the uses the
|
||||||
|
/// SignalIdx in the signal_alias field of Signal::Alias variant to index
|
||||||
|
/// into the signal arena in the all_signals field of the vcd, and returns
|
||||||
|
/// the resulting signal if that signal is a Signal::Data variant, else,
|
||||||
|
/// this function returns an Err.
|
||||||
|
pub fn dealiasing_signal_lookup<'a>(
|
||||||
|
&'a self,
|
||||||
|
signal: &Signal
|
||||||
|
) -> Result<&'a Signal, String> {
|
||||||
|
// dereference signal if Signal::Alias, or keep idx if Signal::Data
|
||||||
|
let signal_idx = match signal {
|
||||||
|
Signal::Data { self_idx, .. } => *self_idx,
|
||||||
|
Signal::Alias { name, signal_alias } => *signal_alias,
|
||||||
|
};
|
||||||
|
|
||||||
// Should now point to Signal::Data variant, or else there's an error
|
// Should now point to Signal::Data variant, or else there's an error
|
||||||
let SignalIdx(idx) = signal_idx;
|
let SignalIdx(idx) = signal_idx;
|
||||||
let signal = self.all_signals.get(idx).unwrap();
|
let signal = self.all_signals.get(idx).unwrap();
|
||||||
|
|
Loading…
Reference in a new issue