Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cosmic Refactor #751

Merged
merged 7 commits into from
Aug 29, 2024
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
83 changes: 39 additions & 44 deletions difftest/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions difftest/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ members = [
"test_common",
"spike_rs",
"offline",
"online_dpi",
"online_drive",
"online_vcs",
"dpi_t1",
"dpi_t1rocket",
"dpi_common",
]
exclude = [
"spike_interfaces"
Expand Down
14 changes: 14 additions & 0 deletions difftest/dpi_common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "dpi_common"
edition = "2021"
version.workspace = true

[dependencies]
svdpi = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }

[features]
vcs = ["svdpi/vpi"]
verilator = ["svdpi/sv2023"]
trace = []
42 changes: 42 additions & 0 deletions difftest/dpi_common/src/dpi_target.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
use std::sync::Mutex;

pub struct DpiTarget<T> {
target: Mutex<Option<T>>,
}

impl<T> DpiTarget<T> {
pub const fn new() -> Self {
Self { target: Mutex::new(None) }
}

#[track_caller]
pub fn init(&self, init_fn: impl FnOnce() -> T) {
let mut target = self.target.lock().unwrap();
if target.is_some() {
panic!("DpiTarget is already initialized");
}
*target = Some(init_fn());
}

#[track_caller]
pub fn with<R>(&self, f: impl FnOnce(&mut T) -> R) -> R {
let mut target = self.target.lock().unwrap();
let target = target.as_mut().expect("DpiTarget is not initialized");
f(target)
}

#[track_caller]
pub fn with_optional<R>(&self, f: impl FnOnce(Option<&mut T>) -> R) -> R {
let mut target = self.target.lock().unwrap();
f(target.as_mut())
}

#[track_caller]
pub fn dispose(&self) {
let mut target = self.target.lock().unwrap();
if target.is_none() {
panic!("DpiTarget is not initialized");
}
*target = None;
}
}
130 changes: 130 additions & 0 deletions difftest/dpi_common/src/dump.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
use svdpi::SvScope;
use tracing::error;

use crate::plusarg::PlusArgMatcher;

pub struct DumpEndError;

#[cfg(feature = "trace")]
pub type DumpControl = RealDumpControl;
#[cfg(not(feature = "trace"))]
pub type DumpControl = EmptyDumpControl;

#[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")]
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());
}
}

#[cfg(feature = "trace")]
pub struct RealDumpControl {
svscope: svdpi::SvScope,
wave_path: String,
dump_start: u64,
dump_end: u64,

started: bool,
}

#[cfg(feature = "trace")]
impl RealDumpControl {
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 from_plusargs(svscope: SvScope, marcher: &PlusArgMatcher) -> Self {
let wave_path = marcher.match_("t1_wave_path");
let dump_range = marcher.try_match("t1_dump_range").unwrap_or("");
Self::new(svscope, wave_path, dump_range)
}

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 from_plusargs(svscope: SvScope, marcher: &PlusArgMatcher) -> Self {
// do nothing
let _ = svscope;
let _ = marcher;
Self {}
}
pub fn start(&mut self) {
// do nothing
}
pub fn trigger_watchdog(&mut self, tick: u64) -> Result<(), DumpEndError> {
// do nothing
let _ = tick;
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)
}
19 changes: 19 additions & 0 deletions difftest/dpi_common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
pub mod dpi_target;
pub mod dump;
pub mod plusarg;

pub use dpi_target::DpiTarget;

use tracing_subscriber::{EnvFilter, FmtSubscriber};

pub fn setup_logger() {
let global_logger = FmtSubscriber::builder()
.with_env_filter(EnvFilter::from_default_env()) // default level: error
.without_time()
.with_target(false)
.with_ansi(true)
.compact()
.finish();
tracing::subscriber::set_global_default(global_logger)
.expect("internal error: fail to setup log subscriber");
}
29 changes: 29 additions & 0 deletions difftest/dpi_common/src/plusarg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
pub struct PlusArgMatcher {
plusargs: Vec<String>,
}

impl PlusArgMatcher {
pub fn from_args() -> Self {
let plusargs = std::env::args().filter(|arg| arg.starts_with('+')).collect();

Self { plusargs }
}

pub fn try_match(&self, arg_name: &str) -> Option<&str> {
let prefix = &format!("+{arg_name}=");

for plusarg in &self.plusargs {
if plusarg.starts_with(prefix) {
return Some(&plusarg[prefix.len()..]);
}
}
None
}

pub fn match_(&self, arg_name: &str) -> &str {
self.try_match(arg_name).unwrap_or_else(|| {
tracing::error!("required plusarg '+{arg_name}=' not found");
panic!("failed to march '+{arg_name}='");
})
}
}
9 changes: 5 additions & 4 deletions difftest/online_dpi/Cargo.toml → difftest/dpi_t1/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
[package]
name = "online_dpi"
name = "dpi_t1"
edition = "2021"
version.workspace = true

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

[lib]
crate-type = ["staticlib"]

[dependencies]
common = { path = "../test_common" }
dpi_common = { path = "../dpi_common" }
spike_rs = { path = "../spike_rs" }
clap = { workspace = true }
tracing = { workspace = true }
svdpi = { workspace = true }
hex = "0.4.3"

[features]
trace = []
Loading