use crate::{error::VcdError, *};
use std::{
io::{BufWriter, Write},
path::Path,
};
fn write_var_def(vcd: &VcdDb, scope: &Scope, w: &mut Vec<u8>) -> std::result::Result<(), VcdError> {
writeln!(w, "&scope {} {} &end", scope.scope_type, scope.scope_name)?;
for var_idx in &scope.variables {
let cur_var = &vcd.variable[*var_idx];
writeln!(
w,
"$var {} {} {} $end",
cur_var.var_type, cur_var.width, cur_var.name
)?;
}
if scope.sub_scope_idx.is_empty() {
writeln!(w, "$upscope $end")?;
} else {
for s_idx in &scope.sub_scope_idx {
let sub_scope = &vcd.scope[*s_idx];
write_var_def(vcd, sub_scope, w)?;
}
}
Ok(())
}
impl VcdDb {
pub fn save_vcd<P: AsRef<Path>>(&self, file: P) -> std::result::Result<(), VcdError> {
let mut file_buffer = BufWriter::new(std::fs::File::create(file)?);
let mut w: Vec<u8> = vec![];
writeln!(&mut w, "$date {} $end", self.date)?;
writeln!(&mut w, "$version {} $end", self.version)?;
writeln!(&mut w, "$comment {} $end", self.comment)?;
writeln!(
&mut w,
"$timescale {}{} $end",
self.timescale.0, self.timescale.1
)?;
let top_scope: &Scope = &self.scope[0];
write_var_def(self, top_scope, &mut w)?;
for (i, t) in self.timestap.clone().into_iter().enumerate() {
writeln!(&mut w, "#{}", t)?;
for v in &self.var_value {
let id: &str = self.value_var_map.get(&i).unwrap();
if let VarValue::Scalar(_) = v[i] {
writeln!(&mut w, "{}{}", v[i], id)?;
} else {
writeln!(&mut w, "{} {}", v[i], id)?;
}
}
}
file_buffer.write_all(&w)?;
file_buffer.flush()?;
Ok(())
}
}