Skip to content
This repository was archived by the owner on Dec 30, 2024. It is now read-only.

Backtrace #3

Merged
merged 2 commits into from
Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ name = "fastwave"
version = "0.1.0"
edition = "2021"

[profile.release]
debug = 1

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
num = "0.4"
clap = { version = "3.1.8", features = ["derive"] }
chrono = "0.4"
itertools = "0.10.3"
itertools = "0.10.3"
backtrace = "0.3"
4 changes: 1 addition & 3 deletions src/vcd/parse/combinator_atoms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ pub(super) fn ident(
) -> Result<(), String> {
// let keyword = "module";

let err : Result<(), String> = Err(format!("reached end of file without parser leaving ident"));
let word = word_reader.next_word();
let (word, cursor) = word.ok_or(err).unwrap();
let (word, cursor) = word_reader.next_word()?;

if word == keyword {
return Ok(())
Expand Down
5 changes: 3 additions & 2 deletions src/vcd/parse/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,10 @@ pub(super) fn parse_events<'a>(

loop {
let next_word = word_reader.next_word();
// if we've reached the end of the file, then there is obviously
// The following is the only case where eof is not an error.
// If we've reached the end of the file, then there is obviously
// nothing left to do...
if next_word.is_none() {break};
if next_word.is_err() {break};

let (word, cursor) = next_word.unwrap();
let Cursor(Line(_), Word(word_in_line_idx)) = cursor;
Expand Down
54 changes: 19 additions & 35 deletions src/vcd/parse/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ pub(super) fn parse_date(

let days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
if !days.contains(&word) {
let msg = format!("Error near {}:{}. Reached end of file without \
terminating parser", file!(), line!());
let msg = format!("Error near {}:{}.", file!(), line!());
let msg2 = format!("{word} is not a valid weekday : expected one of {days:?}\n");
let msg3 = format!("failure location: {cursor:?}");
return Err(format!("{}{}{}", msg, msg2, msg3))
Expand All @@ -38,8 +37,7 @@ pub(super) fn parse_date(
];

if !months.contains(&word) {
let msg = format!("Error near {}:{}. Reached end of file without \
terminating parser", file!(), line!());
let msg = format!("Error near {}:{}.", file!(), line!());
let msg2 = format!("{word} is not a valid month : expected one of {months:?}\n");
let msg3 = format!("failure location: {cursor:?}");
return Err(format!("{}{}{}", msg, msg2, msg3))
Expand All @@ -54,12 +52,11 @@ pub(super) fn parse_date(

let date : u8 = match word.to_string().parse() {
Ok(date) => date,
Err(_) => {return Err("".to_string())}
Err(e) => {return Err(format!("Error near {}:{}. {e}", file!(), line!()))}
};

if date > 31 {
let msg = format!("Error near {}:{}. Reached end of file without \
terminating parser", file!(), line!());
let msg = format!("Error near {}:{}.", file!(), line!());
let msg2 = format!("{word} is not a valid date : must be between 0 and 31\n");
let msg3 = format!("failure location: {cursor:?}");
return Err(format!("{}{}{}", msg, msg2, msg3))
Expand All @@ -77,7 +74,7 @@ pub(super) fn parse_date(
res.assert_match()?;
let hh : u8 = res.matched.to_string()
.parse()
.map_err(|_| "failed to parse".to_string())?;
.map_err(|e| format!("Error near {}:{}. {e}", file!(), line!()))?;

if hh > 23 {
let msg = format!("Error near {}:{}.", file!(), line!());
Expand All @@ -92,7 +89,7 @@ pub(super) fn parse_date(
res.assert_match()?;
let mm : u8 = res.matched.to_string()
.parse()
.map_err(|_| "failed to parse".to_string())?;
.map_err(|e| format!("Error near {}:{}. {e}", file!(), line!()))?;

if mm > 60 {
let msg = format!("Error near {}:{}.", file!(), line!());
Expand All @@ -107,7 +104,7 @@ pub(super) fn parse_date(
let residual = &res.residual[1..]; // chop of colon which is at index 0
let ss : u8 = residual.to_string()
.parse()
.map_err(|_| "failed to parse".to_string())?;
.map_err(|e| format!("Error near {}:{}. {e}", file!(), line!()))?;

if ss > 60 {
let msg = format!("Error near {}:{}.", file!(), line!());
Expand All @@ -132,24 +129,15 @@ pub(super) fn parse_date(
return Ok(full_date.unwrap())
}

Err("failed to parse date".to_string())
Err(format!("Error near {}:{}. Failed to parse date.", file!(), line!()))

}

pub(super) fn parse_version(word_reader : &mut WordReader) -> Result<Version, String> {
let mut version = String::new();

loop {
let word = word_reader.next_word();

// if there isn't another word left in the file, then we exit
if word.is_none() {
let msg = format!("Error near {}:{}. Reached end of file without \
terminating parser", file!(), line!());
return Err(msg)
}

let (word, _) = word.unwrap();
let (word, _) = word_reader.next_word()?;

if word == "$end" {
// truncate trailing whitespace
Expand All @@ -165,60 +153,56 @@ pub(super) fn parse_version(word_reader : &mut WordReader) -> Result<Version, St
}

pub(super) fn parse_timescale(word_reader : &mut WordReader) -> Result<(Option<u32>, Timescale), String> {
let err_msg = format!("Error near {}:{}. No more words left in vcd file.",
file!(), line!());

// we might see `scalarunit $end` or `scalar unit $end`

// we might see `1ps $end` or `1 ps $end`
// first get timescale
let (word, _) = word_reader.next_word().ok_or(&err_msg)?;
let (word, _) = word_reader.next_word()?;
let word = word.to_string();
let ParseResult{matched, residual} = take_while(word.as_str(), digit);
let scalar = matched;

let scalar : u32 = scalar.to_string().parse()
.map_err(|_| &err_msg)?;
.map_err(|e| format!("Error near {}:{}. {e}", file!(), line!()))?;

let timescale = {
if residual == "" {
let (word, _) = word_reader.next_word().ok_or(&err_msg)?;
let (word, _) = word_reader.next_word()?;
let unit = match word {
"fs" => {Ok(Timescale::Fs)}
"ps" => {Ok(Timescale::Ps)}
"ns" => {Ok(Timescale::Ns)}
"us" => {Ok(Timescale::Us)}
"ms" => {Ok(Timescale::Ms)}
"s" => {Ok(Timescale::S)}
_ => {Err(err_msg.to_string())}
_ => {Err(format!("Error near {}:{}. Unknown unit {word}.", file!(), line!()))}
}.unwrap();

(Some(scalar), unit)
}
else {
let unit = match residual {
"fs" => {Ok(Timescale::Fs)}
"ps" => {Ok(Timescale::Ps)}
"ns" => {Ok(Timescale::Ns)}
"us" => {Ok(Timescale::Us)}
"ms" => {Ok(Timescale::Ms)}
"s" => {Ok(Timescale::S)}
_ => {Err(err_msg.to_string())}
_ => {Err(format!("Error near {}:{}. Unknown unit {residual}.", file!(), line!()))}
}.unwrap();

(Some(scalar), unit)
}
};

// then check for the `$end` keyword
let (end, _) = word_reader.next_word().ok_or(&err_msg)?;
let (end, _) = word_reader.next_word()?;
tag(end, "$end").assert_match()?;

return Ok(timescale);

}

pub(super) fn parse_metadata(word_reader : &mut WordReader) -> Result<Metadata, String> {
let err_msg = format!("Error near {}:{}. No more words left in vcd file.",
file!(), line!());

let mut metadata = Metadata {
date : None,
Expand All @@ -228,7 +212,7 @@ pub(super) fn parse_metadata(word_reader : &mut WordReader) -> Result<Metadata,

loop {
// check for another word in the file
let (word, _) = word_reader.next_word().ok_or(&err_msg)?;
let (word, _) = word_reader.next_word()?;

let ParseResult{matched, residual} = tag(word, "$");
match matched {
Expand All @@ -254,7 +238,7 @@ pub(super) fn parse_metadata(word_reader : &mut WordReader) -> Result<Metadata,
let mut lookahead_5_words : Vec<(String, Cursor)> = Vec::new();

for _ in 0..5 {
let (word, cursor) = word_reader.next_word().expect(err_msg.as_str());
let (word, cursor) = word_reader.next_word()?;
let word = word.to_string();
match word.as_str() {
"$end" => {
Expand Down
67 changes: 33 additions & 34 deletions src/vcd/parse/scopes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ pub(super) fn parse_var<'a>(
vcd : &'a mut VCD,
signal_map : &mut HashMap<String, SignalIdx>
) -> Result<(), String> {
let err = format!("Error near {}:{}. No more words left in vcd file.", file!(), line!());
let (word, cursor) = word_reader.next_word().ok_or(&err)?;
let (word, cursor) = word_reader.next_word()?;
let expected_types = ["integer", "parameter", "real", "reg", "string", "wire", "tri1", "time"];

// $var parameter 3 a IDLE $end
Expand All @@ -24,12 +23,14 @@ pub(super) fn parse_var<'a>(
"tri1" => {Ok(SigType::Tri1)}
"time" => {Ok(SigType::Time)}
_ => {
let err = format!("found keyword `{word}` but expected one of {expected_types:?} on {cursor:?}");
let err = format!("Error near {}:{} \
found keyword `{word}` but expected one of \
{expected_types:?} on {cursor:?}", file!(), line!());
Err(err)
}
}?;

let (word, cursor) = word_reader.next_word().ok_or(&err)?;
let (word, cursor) = word_reader.next_word()?;
let parse_err = format!("failed to parse as usize on {cursor:?}");

// $var parameter 3 a IDLE $end
Expand All @@ -48,14 +49,14 @@ pub(super) fn parse_var<'a>(

// $var parameter 3 a IDLE $end
// ^ - signal_alias
let (word, _) = word_reader.next_word().ok_or(&err)?;
let (word, _) = word_reader.next_word()?;
let signal_alias = word.to_string();

// $var parameter 3 a IDLE $end
// ^^^^ - full_signal_name(can extend until $end)
let mut full_signal_name = Vec::<String>::new();
loop {
let (word, _) = word_reader.next_word().ok_or(&err)?;
let (word, _) = word_reader.next_word()?;
match word {
"$end" => {break}
_ => {full_signal_name.push(word.to_string())}
Expand Down Expand Up @@ -145,25 +146,17 @@ fn parse_orphaned_vars<'a>(
parse_var(word_reader, scope_idx, vcd, signal_map)?;

loop {
let next_word = word_reader.next_word();

// we shouldn't reach the end of the file here...
if next_word.is_none() {
let err = format!("Error near {}:{}. No more words left in vcd file.", file!(), line!());
Err(err)?;
};

let (word, cursor) = next_word.unwrap();
let (word, cursor) = word_reader.next_word()?;

match word {
"$var" => {
parse_var(word_reader, scope_idx, vcd, signal_map)?;
}
"$scope" => {break}
_ => {
let (f, l )= (file!(), line!());
let msg = format!("Error near {f}:{l}.\
Expected $scope or $var, found {word} at {cursor:?}");
let msg = format!("Error near {}:{}.\
Expected $scope or $var, found \
{word} at {cursor:?}", file!(), line!());
Err(msg)?;
}
};
Expand All @@ -181,20 +174,21 @@ pub(super) fn parse_signal_tree<'a>(

// $scope module reg_mag_i $end
// ^^^^^^ - module keyword
let err = format!("Error near {}:{}. No more words left in vcd file.", file!(), line!());
let (keyword, cursor) = word_reader.next_word().ok_or(&err)?;
let (keyword, cursor) = word_reader.next_word()?;

let expected = ["module", "begin", "task", "function"];
if expected.contains(&keyword) {
Ok(())
} else {
let err = format!("found keyword `{keyword}` but expected one of `{expected:?}` on {cursor:?}");
let err = format!("Error near {}:{}. \
found keyword `{keyword}` but expected one of \
{expected:?} on {cursor:?}", file!(), line!());
Err(err)
}?;

// $scope module reg_mag_i $end
// ^^^^^^^^^ - scope name
let (scope_name, _) = word_reader.next_word().ok_or(&err)?;
let (scope_name, _) = word_reader.next_word()?;

let curr_scope_idx = ScopeIdx(vcd.all_scopes.len());

Expand Down Expand Up @@ -227,7 +221,7 @@ pub(super) fn parse_signal_tree<'a>(
ident(word_reader, "$end")?;

loop {
let (word, cursor) = word_reader.next_word().ok_or(&err)?;
let (word, cursor) = word_reader.next_word()?;
let ParseResult{matched, residual} = tag(word, "$");
match matched {
// we hope that this word starts with a `$`
Expand All @@ -251,13 +245,18 @@ pub(super) fn parse_signal_tree<'a>(
}
}
_ => {
let err = format!("found keyword `{residual}` but expected `$scope`, `$var`, `$comment`, or `$upscope` on {cursor:?}");
let err = format!("Error near {}:{}. \
found keyword `{residual}` but expected \
`$scope`, `$var`, `$comment`, or `$upscope` \
on {cursor:?}", file!(), line!());
return Err(err)
}
}
}
_ => {
let err = format!("found keyword `{matched}` but expected `$` on {cursor:?}");
let err = format!("Error near {}:{}. \
found keyword `{matched}` but \
expected `$` on {cursor:?}", file!(), line!());
return Err(err)
}
}
Expand All @@ -272,25 +271,24 @@ pub(super) fn parse_scopes<'a>(
signal_map : &mut HashMap<String, SignalIdx>
) -> Result<(), String> {
// get the current word
let err = format!("Error near {}:{}. No more words left in vcd file.", file!(), line!());
let (word, _) = word_reader.curr_word().ok_or(&err)?;
let (word, _) = word_reader.curr_word()?;

// we may have orphaned vars that occur before the first scope
if word == "$var" {
parse_orphaned_vars(word_reader, vcd, signal_map)?;
}

// get the current word
let (word, cursor) = word_reader.curr_word().ok_or(&err)?;
let (word, cursor) = word_reader.curr_word()?;

// the current word should be "scope", as `parse_orphaned_vars`(if it
// was called), should have terminated upon encountering "$scope".
// If `parse_orphaned_vars` was not called, `parse_scopes` should still
// have only been called if the caller encountered the word "$scope"
if word != "$scope" {
let (f, l )= (file!(), line!());
let msg = format!("Error near {f}:{l}.\
Expected $scope or $var, found {word} at {cursor:?}");
let msg = format!("Error near {}:{}.\
Expected $scope or $var, found \
{word} at {cursor:?}", file!(), line!());
return Err(msg)
}

Expand All @@ -305,7 +303,7 @@ pub(super) fn parse_scopes<'a>(
// because this loop gets a word from `next_word` instead of
// `curr_word()`.
loop {
let (word, cursor) = word_reader.next_word().ok_or(&err)?;
let (word, cursor) = word_reader.next_word()?;
match word {
"$scope" => {
parse_signal_tree(word_reader, None, vcd, signal_map)?;
Expand All @@ -322,8 +320,9 @@ pub(super) fn parse_scopes<'a>(
}
}
_ => {
let err = format!("found keyword `{word}` but expected one \
of `{expected_keywords:?}` on {cursor:?}");
let err = format!("Error near {}:{} \
found keyword `{word}` but expected one of \
{expected_keywords:?} on {cursor:?}", file!(), line!());
return Err(err)

}
Expand Down
Loading