diff --git a/crates/fayalite/src/sim/vcd.rs b/crates/fayalite/src/sim/vcd.rs index 8b5a58c..0779b5c 100644 --- a/crates/fayalite/src/sim/vcd.rs +++ b/crates/fayalite/src/sim/vcd.rs @@ -235,6 +235,17 @@ fn write_escaped(writer: &mut W, value: impl Display) -> io::Resul write!(Wrapper(writer), "{value}") } +fn is_unescaped_verilog_identifier(ident: &str) -> bool { + // we only allow ascii, so we can just check bytes + let Some((&first, rest)) = ident.as_bytes().split_first() else { + return false; // empty string is not an identifier + }; + (first.is_ascii_alphabetic() || first == b'_') + && rest + .iter() + .all(|&ch| ch.is_ascii_alphanumeric() || ch == b'_' || ch == b'$') +} + fn write_vcd_var( writer: &mut W, var_type: &str, @@ -244,7 +255,12 @@ fn write_vcd_var( ) -> io::Result<()> { write!(writer, "$var {var_type} {size} ")?; write_scalar_id(writer, id)?; - writeln!(writer, " {name} $end") + writer.write_all(b" ")?; + if !is_unescaped_verilog_identifier(name) { + writer.write_all(b"\\")?; + } + write_escaped(writer, name)?; + writer.write_all(b" $end\n") } impl WriteTrace for TraceUInt {