From 6ee0d4265cf2605ee42386bbd2bcb07b1884759d Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Wed, 17 Jun 2026 18:22:33 -0700 Subject: [PATCH] switch to using fayalite version of checked_vcd_output instead of cpu::util --- crates/cpu/src/util.rs | 149 ------------------ crates/cpu/tests/rename_execute_retire.rs | 2 +- .../tests/simple_power_isa_decoder/main.rs | 5 +- crates/cpu/tests/units_formal.rs | 5 +- 4 files changed, 6 insertions(+), 155 deletions(-) diff --git a/crates/cpu/src/util.rs b/crates/cpu/src/util.rs index ab402ed..6162a19 100644 --- a/crates/cpu/src/util.rs +++ b/crates/cpu/src/util.rs @@ -317,152 +317,3 @@ impl LFSR31 { state } } - -pub struct CheckedVcdOutput { - writer: Option, - expected_path: PathBuf, - expected_contents: Result, std::io::Error)>, - location: &'static Location<'static>, -} - -impl CheckedVcdOutput { - #[must_use] - #[track_caller] - pub fn new(sim: &mut Simulation, expected_path: PathBuf) -> Self { - let writer = RcWriter::default(); - sim.add_trace_writer(VcdWriterDecls::new(writer.clone())); - Self { - writer: Some(writer), - expected_contents: std::fs::read_to_string(&expected_path).map_err(|e| { - eprintln!( - "error: failed to read expected VCD from: {}", - expected_path.display(), - ); - (std::env::current_dir().ok(), e) - }), - expected_path, - location: Location::caller(), - } - } - #[must_use] - #[track_caller] - #[doc(hidden)] - pub fn __checked_vcd_output_macro_helper( - sim: &mut Simulation, - cargo_manifest_dir: &'static str, - path: &'static str, - ) -> Self { - Self::new(sim, Path::new(cargo_manifest_dir).join(path)) - } - pub fn with_vcd_output(&self, f: impl FnOnce(&str) -> R) -> R { - let Some(writer) = &self.writer else { - unreachable!(); - }; - writer.clone().borrow(|output| { - let Ok(output) = str::from_utf8(output) else { - unreachable!("VcdWriter writes valid UTF-8"); - }; - f(output) - }) - } - #[track_caller] - pub fn finish(mut self) { - let Ok(()) = self.finish_impl(|msg| panic!("{msg}")); - } - fn finish_impl( - &mut self, - error: impl FnOnce(std::fmt::Arguments<'_>) -> E, - ) -> Result<(), E> { - let Self { - writer: Some(writer), - expected_path, - expected_contents, - location, - } = self - else { - // already finished - return Ok(()); - }; - let Ok(vcd) = String::from_utf8(writer.take()) else { - unreachable!("VcdWriter writes valid UTF-8"); - }; - let expected_path_d = expected_path.display(); - if expected_contents - .as_ref() - .is_ok_and(|expected_contents| *expected_contents == vcd) - { - // avoid written output from being split from threads interleaving writes to stdout - let _stdout = std::io::stderr().lock(); - // use println to get output captured by tests - println!("\n{location}: generated VCD matches the expected VCD in {expected_path_d}"); - return Ok(()); - } - // avoid written output from being split from threads interleaving writes to stderr - let _stderr = std::io::stderr().lock(); - let error = |msg: std::fmt::Arguments<'_>| { - // print msg at both beginning and end so it's easier to find when the vcd is huge - Err(error(format_args!( - "\n{msg}####### VCD:\n{vcd}\n#######\n{msg}" - ))) - }; - let error = |msg: std::fmt::Arguments<'_>| match &*expected_contents { - Ok(_) => error(format_args!( - "{location}: generated VCD doesn't match the expected VCD in {expected_path_d}\n\ - {msg}", - )), - Err((Some(current_dir), e)) => error(format_args!( - "{location}: generated VCD doesn't match the expected VCD in {expected_path_d}\n\ - error: failed to read: {e}\n\ - current dir: {current_dir}\n\ - {msg}", - current_dir = current_dir.display(), - )), - Err((None, e)) => error(format_args!( - "{location}: generated VCD doesn't match the expected VCD in {expected_path_d}\n\ - error: failed to read: {e}\n\ - {msg}", - )), - }; - const OVERWRITE_VAR_NAME: &str = "OVERWRITE_EXPECTED_VCD"; - const OVERWRITE_VAR_VALUE: &str = "overwrite"; - match std::env::var_os(OVERWRITE_VAR_NAME) { - Some(v) if v == OVERWRITE_VAR_VALUE => match std::fs::write(&expected_path, &vcd) { - Ok(()) => error(format_args!( - "warning: since `{OVERWRITE_VAR_NAME}={OVERWRITE_VAR_VALUE}` is set -- writing the generated VCD to {expected_path_d}\n" - )), - Err(e) => error(format_args!( - "error: since `{OVERWRITE_VAR_NAME}={OVERWRITE_VAR_VALUE}` is set -- tried to write the generated VCD to {expected_path_d}\n\ - error: failed to write: {e}" - )), - }, - _ => error(format_args!( - "note: rerun the test with the environment variable `{OVERWRITE_VAR_NAME}={OVERWRITE_VAR_VALUE}`\n\ - to update the expected output to match the generated output.\n" - )), - } - } -} - -impl Drop for CheckedVcdOutput { - #[track_caller] - fn drop(&mut self) { - let _ = self.finish_impl(|msg| { - if std::thread::panicking() { - eprintln!("{msg}"); // use eprintln to get output captured by tests - } else { - panic!("{msg}"); - } - }); - } -} - -#[macro_export] -macro_rules! checked_vcd_output { - ($sim:expr, $path_relative_to_manifest_dir:expr $(,)?) => { - $crate::util::CheckedVcdOutput::__checked_vcd_output_macro_helper( - $sim, - ::std::env!("CARGO_MANIFEST_DIR"), - ::std::concat!($path_relative_to_manifest_dir), - ) - }; -} diff --git a/crates/cpu/tests/rename_execute_retire.rs b/crates/cpu/tests/rename_execute_retire.rs index 32954b1..ca7db6b 100644 --- a/crates/cpu/tests/rename_execute_retire.rs +++ b/crates/cpu/tests/rename_execute_retire.rs @@ -2,7 +2,6 @@ // See Notices.txt for copyright information use cpu::{ - checked_vcd_output, config::{ CpuConfig, CpuConfigFetchWidth, CpuConfigMaxUnitMaxInFlight, PhantomConstCpuConfig, UnitConfig, @@ -29,6 +28,7 @@ use cpu::{ }; use fayalite::{ bundle::BundleType, + checked_vcd_output, module::instance_with_loc, prelude::*, ty::{OpaqueSimValue, StaticType}, diff --git a/crates/cpu/tests/simple_power_isa_decoder/main.rs b/crates/cpu/tests/simple_power_isa_decoder/main.rs index 30dac0b..40c2713 100644 --- a/crates/cpu/tests/simple_power_isa_decoder/main.rs +++ b/crates/cpu/tests/simple_power_isa_decoder/main.rs @@ -3,10 +3,9 @@ use crate::test_cases::TestCase; use cpu::{ - checked_vcd_output, decoder::simple_power_isa::decode_one_insn, instruction::MOp, - util::array_vec::ArrayVec, + decoder::simple_power_isa::decode_one_insn, instruction::MOp, util::array_vec::ArrayVec, }; -use fayalite::prelude::*; +use fayalite::{checked_vcd_output, prelude::*}; use std::{fmt::Write as _, io::Write, process::Command}; mod test_cases; diff --git a/crates/cpu/tests/units_formal.rs b/crates/cpu/tests/units_formal.rs index 7735322..f683307 100644 --- a/crates/cpu/tests/units_formal.rs +++ b/crates/cpu/tests/units_formal.rs @@ -18,6 +18,7 @@ use cpu::{ util::array_vec::ArrayVec, }; use fayalite::{ + checked_vcd_output, firrtl::ExportOptions, module::{instance_with_loc, transform::simplify_enums::SimplifyEnumsKind, wire_with_loc}, prelude::*, @@ -802,7 +803,7 @@ fn test_power_isa_add_sim() { let any_consts = AnyConsts::new(); let m = check_power_isa_alu_formal(config, cases_add_sub(), Some(any_consts)); let mut sim = Simulation::new(m); - let _checked_vcd_output = cpu::checked_vcd_output!( + let _checked_vcd_output = checked_vcd_output!( &mut sim, "tests/expected/units_formal_power_isa_add_sim.vcd", ); @@ -847,7 +848,7 @@ fn test_power_isa_paddi_sim() { let any_consts = AnyConsts::new(); let m = check_power_isa_alu_formal(config, cases_add_sub(), Some(any_consts)); let mut sim = Simulation::new(m); - let _checked_vcd_output = cpu::checked_vcd_output!( + let _checked_vcd_output = checked_vcd_output!( &mut sim, "tests/expected/units_formal_power_isa_paddi_sim.vcd", );