handle case of signal events with bitwidths shorter than nominal signal length

This commit is contained in:
Yehowshua Immanuel 2022-08-02 11:51:07 -04:00
parent d70a09e255
commit b685bf8be7

View file

@ -273,12 +273,12 @@ fn parse_events<'a>(
// Also account for the error case of a bitwidth of `None` // Also account for the error case of a bitwidth of `None`
match num_bits { match num_bits {
Some(ref num_bits) => { Some(ref num_bits) => {
if *num_bits > observed_num_bits { if observed_num_bits > *num_bits {
let (f, l) = (file!(), line!()); let (f, l) = (file!(), line!());
let msg = format!("\ let msg = format!("\
Error near {f}:{l}. The bitwidth for signal {name} \ Error near {f}:{l}. The bitwidth for signal {name} \
of sig_type {sig_type:?} is expected to be `1` not \ of sig_type {sig_type:?} is expected to be `{num_bits}` not \
`{num_bits}`. \ `{observed_num_bits}`. \
This error occurred while parsing the vcd file at \ This error occurred while parsing the vcd file at \
{cursor:?}"); {cursor:?}");
*signal_error = Some(msg); *signal_error = Some(msg);
@ -309,7 +309,31 @@ fn parse_events<'a>(
} }
else { else {
u8_timeline_markers.push(timeline_idx); u8_timeline_markers.push(timeline_idx);
let mut curr_num_bytes = value_u8.len();
u8_timeline.append(&mut value_u8); u8_timeline.append(&mut value_u8);
// 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 num_bits = num_bits.unwrap();
let bytes_required = (num_bits / 8) +
if (num_bits % 8) > 0 {1} else {0};
while curr_num_bytes < bytes_required {
// useful for debugging
// let err = format!("Error at {cursor:?}.\
// num_bits = {num_bits}, \
// observed_bits = {observed_num_bits}, \
// curr_num_bytes = {curr_num_bytes}, \
// bytes_required = {bytes_required} \
// for signal {name}");
// Err(err)?;
u8_timeline.push(0u8);
curr_num_bytes += 1;
}
Ok(()) Ok(())
} }
} }
@ -402,6 +426,83 @@ fn parse_events<'a>(
}?; }?;
} }
"1" => {
// lokup signal idx
let hash = &word[1..];
let (f, l )= (file!(), line!());
let Signal_Idx(ref signal_idx) = signal_map.get(hash).ok_or(
format!("Error near {f}:{l}. Failed to lookup signal {hash} at {cursor:?}"))?;
// account for fact that signal idx could be an alias, so there
// could be one step of indirection
let signal_idx =
{
let signal = vcd.all_signals.get(*signal_idx).unwrap();
match signal {
Signal::Data {..} => {*signal_idx}
Signal::Alias {name, signal_alias} => {
let Signal_Idx(ref signal_idx) = signal_alias;
signal_idx.clone()
}
}
};
// after handling potential indirection, go ahead and update the timeline
// of the signal signal_idx references
let signal = vcd.all_signals.get_mut(signal_idx).unwrap();
match signal {
Signal::Data {name, sig_type, ref mut signal_error, num_bits,
self_idx, u8_timeline, u8_timeline_markers, scope_parent, ..} => {
// if this is a bad signal, go ahead and skip it
if signal_error.is_some() {continue;}
// Get bitwidth and verify that it is 1.
// Also account for the error case of a bitwidth of `None`
match num_bits {
Some(ref num_bits) => {
if *num_bits != 1 {
let (f, l) = (file!(), line!());
let msg = format!("\
Error near {f}:{l}. The bitwidth for signal {name} \
of sig_type {sig_type:?} is expected to be `1` not \
`{num_bits}`. \
This error occurred while parsing the vcd file at \
{cursor:?}");
*signal_error = Some(msg);
continue;
}
}
None => {
let (f, l) = (file!(), line!());
let msg = format!("\
Error near {f}:{l}. The bitwidth for signal {name} \
must be specified for a signal of type {sig_type:?}. \
This error occurred while parsing the vcd file at \
{cursor:?}");
Err(msg)?;
}
};
let (f, l )= (file!(), line!());
let timeline_idx = u32::try_from(vcd.timeline.len()).map_err(
|e| format!("Error near {f}:{l}. Failed to convert from usize to u32."))?;
let timeline_idx = TimelineIdx(timeline_idx);
u8_timeline_markers.push(timeline_idx);
u8_timeline.push(1u8);
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)
}
}?;
}
// other one bit cases // other one bit cases
"x" | "X" | "z" | "Z" | "u" | "U" => { "x" | "X" | "z" | "Z" | "u" | "U" => {
let val = word.to_string(); let val = word.to_string();
@ -482,83 +583,6 @@ fn parse_events<'a>(
} }
}?; }?;
} }
"1" => {
// lokup signal idx
let hash = &word[1..];
let (f, l )= (file!(), line!());
let Signal_Idx(ref signal_idx) = signal_map.get(hash).ok_or(
format!("Error near {f}:{l}. Failed to lookup signal {hash} at {cursor:?}"))?;
// account for fact that signal idx could be an alias, so there
// could be one step of indirection
let signal_idx =
{
let signal = vcd.all_signals.get(*signal_idx).unwrap();
match signal {
Signal::Data {..} => {*signal_idx}
Signal::Alias {name, signal_alias} => {
let Signal_Idx(ref signal_idx) = signal_alias;
signal_idx.clone()
}
}
};
// after handling potential indirection, go ahead and update the timeline
// of the signal signal_idx references
let signal = vcd.all_signals.get_mut(signal_idx).unwrap();
match signal {
Signal::Data {name, sig_type, ref mut signal_error, num_bits,
self_idx, u8_timeline, u8_timeline_markers, scope_parent, ..} => {
// if this is a bad signal, go ahead and skip it
if signal_error.is_some() {continue;}
// Get bitwidth and verify that it is 1.
// Also account for the error case of a bitwidth of `None`
match num_bits {
Some(ref num_bits) => {
if *num_bits != 1 {
let (f, l) = (file!(), line!());
let msg = format!("\
Error near {f}:{l}. The bitwidth for signal {name} \
of sig_type {sig_type:?} is expected to be `1` not \
`{num_bits}`. \
This error occurred while parsing the vcd file at \
{cursor:?}");
*signal_error = Some(msg);
continue;
}
}
None => {
let (f, l) = (file!(), line!());
let msg = format!("\
Error near {f}:{l}. The bitwidth for signal {name} \
must be specified for a signal of type {sig_type:?}. \
This error occurred while parsing the vcd file at \
{cursor:?}");
Err(msg)?;
}
};
let (f, l )= (file!(), line!());
let timeline_idx = u32::try_from(vcd.timeline.len()).map_err(
|e| format!("Error near {f}:{l}. Failed to convert from usize to u32."))?;
let timeline_idx = TimelineIdx(timeline_idx);
u8_timeline_markers.push(timeline_idx);
u8_timeline.push(1u8);
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)
}
}?;
}
_ => {} _ => {}
} }