From 3b30253354dfb8013c4b24d2b0f2c3c6004b7b31 Mon Sep 17 00:00:00 2001 From: Shupei Fan Date: Tue, 27 Aug 2024 16:56:27 +0000 Subject: [PATCH] [difftest] move wave dump logic to 'dpi_common' --- difftest/dpi_common/src/dump.rs | 109 ++++++++++++++++++++++++++++++++ difftest/dpi_common/src/lib.rs | 2 + difftest/dpi_t1/src/dpi.rs | 20 ------ difftest/dpi_t1/src/drive.rs | 90 ++++++-------------------- difftest/offline/src/main.rs | 5 +- 5 files changed, 134 insertions(+), 92 deletions(-) create mode 100644 difftest/dpi_common/src/dump.rs diff --git a/difftest/dpi_common/src/dump.rs b/difftest/dpi_common/src/dump.rs new file mode 100644 index 000000000..746d44723 --- /dev/null +++ b/difftest/dpi_common/src/dump.rs @@ -0,0 +1,109 @@ +use svdpi::SvScope; +use tracing::error; + +mod dpi_export { + use std::ffi::c_char; + extern "C" { + /// `export "DPI-C" function dump_wave(input string file)` + pub fn dump_wave(path: *const c_char); + } +} + +fn dump_wave(scope: svdpi::SvScope, path: &str) { + use std::ffi::CString; + let path_cstring = CString::new(path).unwrap(); + + svdpi::set_scope(scope); + unsafe { + dpi_export::dump_wave(path_cstring.as_ptr()); + } +} + +pub struct DumpEndError; + +pub struct RealDumpControl { + svscope: svdpi::SvScope, + wave_path: String, + dump_start: u64, + dump_end: u64, + + started: bool, +} + +impl RealDumpControl { + pub fn new(svscope: SvScope, wave_path: &str, dump_range: &str) -> Self { + let (dump_start, dump_end) = parse_range(dump_range); + Self { + svscope, + wave_path: wave_path.to_owned(), + dump_start, + dump_end, + + started: false, + } + } + + pub fn start(&mut self) { + if !self.started { + dump_wave(self.svscope, &self.wave_path); + self.started = true; + } + } + + pub fn trigger_watchdog(&mut self, tick: u64) -> Result<(), DumpEndError> { + if self.dump_end != 0 && tick > self.dump_end { + return Err(DumpEndError); + } + + if tick >= self.dump_start { + self.start(); + } + + Ok(()) + } +} + +pub struct EmptyDumpControl {} +impl EmptyDumpControl { + pub fn new() -> Self { + Self {} + } + pub fn start(&mut self) { + // do nothing + } + pub fn trigger_watchdog(&mut self, _tick: u64) -> Result<(), DumpEndError> { + // do nothing + Ok(()) + } +} + +fn parse_range(input: &str) -> (u64, u64) { + if input.is_empty() { + return (0, 0); + } + + let parts: Vec<&str> = input.split(",").collect(); + + if parts.len() != 1 && parts.len() != 2 { + error!("invalid dump wave range: `{input}` was given"); + return (0, 0); + } + + const INVALID_NUMBER: &'static str = "invalid number"; + + if parts.len() == 1 { + return (parts[0].parse().expect(INVALID_NUMBER), 0); + } + + if parts[0].is_empty() { + return (0, parts[1].parse().expect(INVALID_NUMBER)); + } + + let start = parts[0].parse().expect(INVALID_NUMBER); + let end = parts[1].parse().expect(INVALID_NUMBER); + if start > end { + panic!("dump start is larger than end: `{input}`"); + } + + (start, end) +} diff --git a/difftest/dpi_common/src/lib.rs b/difftest/dpi_common/src/lib.rs index d98bfe863..617be70f7 100644 --- a/difftest/dpi_common/src/lib.rs +++ b/difftest/dpi_common/src/lib.rs @@ -1,3 +1,5 @@ +pub mod dump; + use tracing_subscriber::{EnvFilter, FmtSubscriber}; pub fn setup_logger() { diff --git a/difftest/dpi_t1/src/dpi.rs b/difftest/dpi_t1/src/dpi.rs index 5dc622b5c..bf7891547 100644 --- a/difftest/dpi_t1/src/dpi.rs +++ b/difftest/dpi_t1/src/dpi.rs @@ -274,23 +274,3 @@ unsafe extern "C" fn retire_vector_mem(dummy: *const SvBitVecVal) { //-------------------------------- // import functions and wrappers //-------------------------------- - -#[cfg(feature = "trace")] -mod dpi_export { - use std::ffi::c_char; - extern "C" { - /// `export "DPI-C" function dump_wave(input string file)` - pub fn dump_wave(path: *const c_char); - } -} - -#[cfg(feature = "trace")] -pub(crate) fn dump_wave(scope: svdpi::SvScope, path: &str) { - use std::ffi::CString; - let path_cstring = CString::new(path).unwrap(); - - svdpi::set_scope(scope); - unsafe { - dpi_export::dump_wave(path_cstring.as_ptr()); - } -} diff --git a/difftest/dpi_t1/src/drive.rs b/difftest/dpi_t1/src/drive.rs index a02e4123e..6610b1051 100644 --- a/difftest/dpi_t1/src/drive.rs +++ b/difftest/dpi_t1/src/drive.rs @@ -1,3 +1,4 @@ +use dpi_common::dump; use spike_rs::runner::SpikeRunner; use spike_rs::runner::{SpikeArgs, MEM_SIZE}; use spike_rs::spike_event::MemAccessRecord; @@ -95,21 +96,18 @@ impl ShadowMem { } } +#[cfg(feature = "trace")] +type DumpControl = dump::RealDumpControl; +#[cfg(not(feature = "trace"))] +type DumpControl = dump::EmptyDumpControl; + pub(crate) struct Driver { spike_runner: SpikeRunner, // SvScope from t1_cosim_init - #[cfg(feature = "trace")] scope: SvScope, - #[cfg(feature = "trace")] - wave_path: String, - #[cfg(feature = "trace")] - dump_start: u64, - #[cfg(feature = "trace")] - dump_end: u64, - #[cfg(feature = "trace")] - dump_started: bool, + dump_control: DumpControl, pub(crate) dlen: u32, @@ -123,42 +121,13 @@ pub(crate) struct Driver { shadow_mem: ShadowMem, } -#[cfg(feature = "trace")] -fn parse_range(input: &str) -> (u64, u64) { - if input.is_empty() { - return (0, 0); - } - - let parts: Vec<&str> = input.split(",").collect(); - - if parts.len() != 1 && parts.len() != 2 { - error!("invalid dump wave range: `{input}` was given"); - return (0, 0); - } - - const INVALID_NUMBER: &'static str = "invalid number"; - - if parts.len() == 1 { - return (parts[0].parse().expect(INVALID_NUMBER), 0); - } - - if parts[0].is_empty() { - return (0, parts[1].parse().expect(INVALID_NUMBER)); - } - - let start = parts[0].parse().expect(INVALID_NUMBER); - let end = parts[1].parse().expect(INVALID_NUMBER); - if start > end { - panic!("dump start is larger than end: `{input}`"); - } - - (start, end) -} - impl Driver { pub(crate) fn new(scope: SvScope, args: &OnlineArgs) -> Self { #[cfg(feature = "trace")] - let (dump_start, dump_end) = parse_range(&args.dump_range); + let dump_control = DumpControl::new(scope, &args.wave_path, &args.dump_range); + + #[cfg(not(feature = "trace"))] + let dump_control = DumpControl::new(); let mut self_ = Self { spike_runner: SpikeRunner::new( @@ -172,16 +141,8 @@ impl Driver { false, ), - #[cfg(feature = "trace")] scope, - #[cfg(feature = "trace")] - wave_path: args.wave_path.to_owned(), - #[cfg(feature = "trace")] - dump_start, - #[cfg(feature = "trace")] - dump_end, - #[cfg(feature = "trace")] - dump_started: false, + dump_control, dlen: args.dlen, timeout: args.timeout, @@ -263,19 +224,15 @@ impl Driver { ); WATCHDOG_TIMEOUT } else { - #[cfg(feature = "trace")] - if self.dump_end != 0 && tick > self.dump_end { - info!( - "[{tick}] run to dump end, exiting (last_commit_cycle={})", - self.last_commit_cycle - ); - return WATCHDOG_TIMEOUT; - } - - #[cfg(feature = "trace")] - if !self.dump_started && tick >= self.dump_start { - self.start_dump_wave(); - self.dump_started = true; + match self.dump_control.trigger_watchdog(tick) { + Ok(()) => {} + Err(dump::DumpEndError) => { + info!( + "[{tick}] run to dump end, exiting (last_commit_cycle={})", + self.last_commit_cycle + ); + return WATCHDOG_TIMEOUT; + } } trace!("[{}] watchdog continue", get_t()); @@ -283,11 +240,6 @@ impl Driver { } } - #[cfg(feature = "trace")] - fn start_dump_wave(&mut self) { - dump_wave(self.scope, &self.wave_path); - } - pub(crate) fn step(&mut self) -> SpikeEvent { // there will be a vfence / scalar load / scalar store in the commit queue's front if let Some(se) = self.spike_runner.commit_queue.front() { diff --git a/difftest/offline/src/main.rs b/difftest/offline/src/main.rs index 6dcc74887..c4830a910 100644 --- a/difftest/offline/src/main.rs +++ b/difftest/offline/src/main.rs @@ -99,9 +99,8 @@ fn main() -> anyhow::Result<()> { fn setup_logger() { // default to WARN level - let env_filer = EnvFilter::builder() - .with_default_directive(LevelFilter::WARN.into()) - .from_env_lossy(); + let env_filer = + EnvFilter::builder().with_default_directive(LevelFilter::WARN.into()).from_env_lossy(); let global_logger = FmtSubscriber::builder() .with_env_filter(env_filer)