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

Pass design parameters by verilog parameters #885

Merged
merged 3 commits into from
Dec 7, 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
22 changes: 18 additions & 4 deletions difftest/Cargo.lock

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

3 changes: 2 additions & 1 deletion difftest/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ members = [
"spike_rs",
"offline_t1emu",
"offline_t1rocketemu",
"offline_common",
"dpi_t1emu",
"dpi_t1rocketemu",
"dpi_common",
Expand All @@ -23,4 +24,4 @@ tracing-subscriber = { version = "0.3", features = ["env-filter", "ansi"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
num-bigint = "0.4.6"
svdpi = "0.0.1"
svdpi = "0.0.3"
80 changes: 51 additions & 29 deletions difftest/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -14,50 +14,72 @@ assert let
available = [ "dpi_t1emu" "dpi_t1rocketemu" "offline_t1emu" "offline_t1rocketemu" ];
in
lib.assertMsg (lib.elem moduleType available) "moduleType is not in ${lib.concatStringsSep ", " available}";
# if emuType is empty, then moduleType must be offline-*, or user should give valid emuType
assert lib.assertMsg ((emuType == "" && lib.hasPrefix "offline" moduleType) || (lib.elem emuType [ "verilator" "vcs" ])) "emuType is either 'vcs' nor 'verilator'";

rustPlatform.buildRustPackage {
name = outputName;
src = with lib.fileset; toSource {
let
rustSrc = with lib.fileset; toSource {
root = ./.;
fileset = unions [
./spike_rs
./offline_t1emu
./offline_t1rocketemu
./dpi_common
./dpi_t1emu
./dpi_t1rocketemu
./offline_common
./offline_t1emu
./offline_t1rocketemu
./Cargo.lock
./Cargo.toml
./.rustfmt.toml
];
};
in
if (lib.hasPrefix "dpi" moduleType) then
assert lib.assertMsg (lib.elem emuType [ "verilator" "vcs" ]) "emuType must be 'vcs' or 'verilator' for dpi";
rustPlatform.buildRustPackage {
name = outputName;
src = rustSrc;

buildFeatures = [ ] ++ lib.optionals (lib.hasPrefix "dpi" moduleType) [ "dpi_common/${emuType}" ];
buildAndTestSubdir = "./${moduleType}";
buildFeatures = [ ] ++ [ "dpi_common/${emuType}" ];
buildAndTestSubdir = "./${moduleType}";

env = {
SPIKE_LIB_DIR = "${libspike}/lib";
SPIKE_INTERFACES_LIB_DIR = "${libspike_interfaces}/lib";
DESIGN_VLEN = rtlDesignMetadata.vlen;
DESIGN_DLEN = rtlDesignMetadata.dlen;
SPIKE_ISA_STRING = rtlDesignMetadata.march;
};
env = {
SPIKE_LIB_DIR = "${libspike}/lib";
SPIKE_INTERFACES_LIB_DIR = "${libspike_interfaces}/lib";
};

cargoLock = {
lockFile = ./Cargo.lock;
};
cargoLock = {
lockFile = ./Cargo.lock;
};

postInstall = lib.optionalString (lib.hasPrefix "offline" moduleType) ''
exe=$(find $out/bin -type f -name 'offline_*')
ln -s "$exe" $out/bin/offline
'';
passthru = {
# include "lib" prefix, without ".so" suffix, for "-sv_lib" option
svLibName = "lib${moduleType}";

passthru = {
# include "lib" prefix, without ".so" suffix, for "-sv_lib" option
svLibName = "lib${moduleType}";
dpiLibPath = "/lib/libdpi_${moduleType}.a";
};
}
else
assert lib.assertMsg (emuType == "") "emuType shall not be set for offline";
rustPlatform.buildRustPackage {
name = outputName;
src = rustSrc;

dpiLibPath = "/lib/libdpi_${moduleType}.a";
};
}
buildFeatures = [ ];
buildAndTestSubdir = "./${moduleType}";

env = {
SPIKE_LIB_DIR = "${libspike}/lib";
SPIKE_INTERFACES_LIB_DIR = "${libspike_interfaces}/lib";
DESIGN_VLEN = rtlDesignMetadata.vlen;
DESIGN_DLEN = rtlDesignMetadata.dlen;
SPIKE_ISA_STRING = rtlDesignMetadata.march;
};

cargoLock = {
lockFile = ./Cargo.lock;
};

postInstall = ''
exe=$(find $out/bin -type f -name 'offline_*')
ln -s "$exe" $out/bin/offline
'';
}
27 changes: 20 additions & 7 deletions difftest/dpi_t1emu/src/dpi.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
#![allow(non_snake_case)]
#![allow(unused_variables)]

use dpi_common::plusarg::PlusArgMatcher;
use dpi_common::DpiTarget;
use std::ffi::c_longlong;
use svdpi::dpi::param::InStr;
use tracing::debug;

use crate::drive::Driver;
use crate::OnlineArgs;
use crate::drive::{Driver, OnlineArgs};
use svdpi::SvScope;

pub type SvBitVecVal = u32;
Expand Down Expand Up @@ -217,17 +216,31 @@ unsafe extern "C" fn axi_write_indexedAccessPort(
}

#[no_mangle]
unsafe extern "C" fn t1_cosim_init() {
let plusargs = PlusArgMatcher::from_args();
let args = OnlineArgs::from_plusargs(&plusargs);

unsafe extern "C" fn t1_cosim_init(
elf_file: InStr<'_>,
dlen: i32,
vlen: i32,
spike_isa: InStr<'_>,
) {
dpi_common::setup_logger();

let scope = SvScope::get_current().expect("failed to get scope in t1_cosim_init");

let args = OnlineArgs {
elf_file: elf_file.get().to_str().unwrap().into(),
log_file: None,
dlen: dlen as u32,
vlen: vlen as u32,
spike_isa: spike_isa.get().to_str().unwrap().into(),
};
TARGET.init(|| Driver::new(scope, &args));
}

#[no_mangle]
unsafe extern "C" fn t1_cosim_set_timeout(timeout: u64) {
TARGET.with(|driver| driver.set_timeout(timeout));
}

#[no_mangle]
unsafe extern "C" fn t1_cosim_final() {
TARGET.with(|driver| {
Expand Down
40 changes: 31 additions & 9 deletions difftest/dpi_t1emu/src/drive.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::path::Path;

use spike_rs::runner::SpikeRunner;
use spike_rs::runner::{SpikeArgs, MEM_SIZE};
use spike_rs::spike_event::MemAccessRecord;
Expand All @@ -7,7 +9,6 @@ use tracing::{debug, error, info, trace};

use crate::dpi::*;
use crate::get_t;
use crate::OnlineArgs;
use svdpi::SvScope;

struct ShadowMem {
Expand Down Expand Up @@ -95,6 +96,23 @@ impl ShadowMem {
}
}

pub(crate) struct OnlineArgs {
/// Path to the ELF file
pub elf_file: String,

/// Path to the log file
pub log_file: Option<String>,

/// vlen config
pub vlen: u32,

/// dlen config
pub dlen: u32,

/// ISA config
pub spike_isa: String,
}

pub(crate) struct Driver {
spike_runner: SpikeRunner,

Expand All @@ -118,15 +136,15 @@ pub(crate) struct Driver {

impl Driver {
pub(crate) fn new(scope: SvScope, args: &OnlineArgs) -> Self {
let elf_file = Path::new(&args.elf_file);
let mut self_ = Self {
spike_runner: SpikeRunner::new(
&SpikeArgs {
elf_file: args.elf_file.clone(),
log_file: args.log_file.clone(),
log_level: "info".to_string(),
elf_file: elf_file.to_owned(),
log_file: args.log_file.as_ref().map(From::from),
vlen: args.vlen,
dlen: args.dlen,
set: args.set.clone(),
set: args.spike_isa.clone(),
},
false,
),
Expand All @@ -135,16 +153,16 @@ impl Driver {
success: false,

dlen: args.dlen,
timeout: args.timeout,
timeout: 0,
last_commit_cycle: 0,

issued: 0,
vector_lsu_count: 0,
shadow_mem: ShadowMem::new(),
};
self_.spike_runner.load_elf(&args.elf_file).unwrap();
self_.spike_runner.load_elf(elf_file).unwrap();

load_elf_to_buffer(&mut self_.shadow_mem.mem, &args.elf_file).unwrap();
load_elf_to_buffer(&mut self_.shadow_mem.mem, elf_file).unwrap();
self_
}

Expand Down Expand Up @@ -204,6 +222,10 @@ impl Driver {
);
}

pub(crate) fn set_timeout(&mut self, timeout: u64) {
self.timeout = timeout;
}

pub(crate) fn watchdog(&mut self) -> u8 {
let tick = get_t();

Expand All @@ -212,7 +234,7 @@ impl Driver {
return WATCHDOG_QUIT;
}

if tick - self.last_commit_cycle > self.timeout {
if self.timeout > 0 && tick - self.last_commit_cycle > self.timeout {
error!(
"[{tick}] watchdog timeout (last_commit_cycle={})",
self.last_commit_cycle
Expand Down
43 changes: 0 additions & 43 deletions difftest/dpi_t1emu/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,49 +1,6 @@
use std::path::PathBuf;

use dpi_common::plusarg::PlusArgMatcher;

pub mod dpi;
pub mod drive;

pub(crate) struct OnlineArgs {
/// Path to the ELF file
pub elf_file: PathBuf,

/// Path to the log file
pub log_file: Option<PathBuf>,

/// vlen config
pub vlen: u32,

/// dlen config
pub dlen: u32,

/// ISA config
pub set: String,

// default to TIMEOUT_DEFAULT
pub timeout: u64,
}

const TIMEOUT_DEFAULT: u64 = 1000000;

impl OnlineArgs {
pub fn from_plusargs(matcher: &PlusArgMatcher) -> Self {
Self {
elf_file: matcher.match_("t1_elf_file").into(),
log_file: matcher.try_match("t1_log_file").map(|x| x.into()),

vlen: env!("DESIGN_VLEN").parse().unwrap(),
dlen: env!("DESIGN_DLEN").parse().unwrap(),
set: env!("SPIKE_ISA_STRING").parse().unwrap(),
timeout: matcher
.try_match("t1_timeout")
.map(|x| x.parse().unwrap())
.unwrap_or(TIMEOUT_DEFAULT),
}
}
}

// keep in sync with TestBench.verbatimModule
// the value is measured in simulation time unit
pub const CYCLE_PERIOD: u64 = 20000;
Expand Down
Loading