diff --git a/difftest/Cargo.lock b/difftest/Cargo.lock index 7c67dc680..14b0f1a16 100644 --- a/difftest/Cargo.lock +++ b/difftest/Cargo.lock @@ -124,17 +124,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" -[[package]] -name = "common" -version = "0.1.0" -dependencies = [ - "anyhow", - "clap", - "spike_rs", - "tracing", - "tracing-subscriber", -] - [[package]] name = "dpi_common" version = "0.1.0" @@ -285,7 +274,22 @@ version = "0.1.0" dependencies = [ "anyhow", "clap", - "common", + "libloading", + "num-bigint", + "serde", + "serde_json", + "spike_rs", + "tracing", + "tracing-subscriber", + "xmas-elf", +] + +[[package]] +name = "offline_t1rocket" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", "libloading", "num-bigint", "serde", @@ -433,8 +437,10 @@ name = "spike_rs" version = "0.1.0" dependencies = [ "anyhow", + "clap", "libc", "tracing", + "tracing-subscriber", "xmas-elf", ] diff --git a/difftest/Cargo.toml b/difftest/Cargo.toml index 4328b6b4e..06f733a27 100644 --- a/difftest/Cargo.toml +++ b/difftest/Cargo.toml @@ -1,9 +1,9 @@ [workspace] resolver = "2" members = [ - "test_common", "spike_rs", "offline_t1", + "offline_t1rocket", "dpi_t1", "dpi_t1rocket", "dpi_common", diff --git a/difftest/default.nix b/difftest/default.nix index 2234a7ce6..528f1a06a 100644 --- a/difftest/default.nix +++ b/difftest/default.nix @@ -29,7 +29,6 @@ rustPlatform.buildRustPackage { ./dpi_common ./dpi_t1 ./dpi_t1rocket - ./test_common ./Cargo.lock ./Cargo.toml ]; diff --git a/difftest/dpi_t1/src/drive.rs b/difftest/dpi_t1/src/drive.rs index 8a39ffc94..d63485cd1 100644 --- a/difftest/dpi_t1/src/drive.rs +++ b/difftest/dpi_t1/src/drive.rs @@ -124,6 +124,7 @@ impl Driver { &SpikeArgs { elf_file: args.elf_file.clone(), log_file: args.log_file.clone(), + log_level: "info".to_string(), vlen: args.vlen, dlen: args.dlen, set: args.set.clone(), diff --git a/difftest/offline_t1/Cargo.toml b/difftest/offline_t1/Cargo.toml index aada692da..8d77199be 100644 --- a/difftest/offline_t1/Cargo.toml +++ b/difftest/offline_t1/Cargo.toml @@ -15,5 +15,4 @@ num-bigint = { workspace = true } libloading = "0.8.1" xmas-elf = "0.9.1" -common = { path = "../test_common" } spike_rs = { path = "../spike_rs" } diff --git a/difftest/offline_t1/src/difftest.rs b/difftest/offline_t1/src/difftest.rs index 66a0173d9..454edb09e 100644 --- a/difftest/offline_t1/src/difftest.rs +++ b/difftest/offline_t1/src/difftest.rs @@ -1,9 +1,5 @@ -use common::spike_runner::SpikeRunner; +use spike_rs::runner::*; use std::path::Path; -use tracing::info; - -use common::rtl_config::RTLConfig; -use common::CommonArgs; use crate::dut::Dut; use crate::json_events::*; @@ -11,20 +7,15 @@ use crate::json_events::*; pub struct Difftest { runner: SpikeRunner, dut: Dut, - - #[allow(dead_code)] - config: RTLConfig, } impl Difftest { - pub fn new(args: CommonArgs) -> Self { - let config = RTLConfig { vlen: args.vlen, dlen: args.dlen }; + pub fn new(args: SpikeArgs) -> Self { Self { runner: SpikeRunner::new(&args, true), dut: Dut::new(Path::new( &args.log_file.expect("difftest must be run with a log file"), )), - config, } } @@ -39,9 +30,7 @@ impl Difftest { Ok(()) } JsonEvents::SimulationStop { reason, cycle } => { - info!("simulation stopped at cycle {}, reason {}", cycle, reason); - self.runner.cycle = *cycle; - Ok(()) + anyhow::bail!("stop: simulation stopped at cycle {cycle}, reason {reason}") } JsonEvents::Issue { idx, cycle } => { self.runner.cycle = *cycle; diff --git a/difftest/offline_t1/src/json_events.rs b/difftest/offline_t1/src/json_events.rs index 24652f04d..1244cfd74 100644 --- a/difftest/offline_t1/src/json_events.rs +++ b/difftest/offline_t1/src/json_events.rs @@ -1,18 +1,9 @@ -use common::spike_runner::SpikeRunner; use num_bigint::BigUint; use serde::{Deserialize, Deserializer}; +use spike_rs::runner::SpikeRunner; use spike_rs::spike_event::LSU_IDX_DEFAULT; use tracing::{debug, info}; -#[derive(Deserialize, Debug, PartialEq, Clone)] -pub enum Opcode { - PutFullData = 0, - PutPartialData = 1, - Get = 4, - // AccessAckData = 0, - // AccessAck = 0, -} - fn bigint_to_vec_u8<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, diff --git a/difftest/offline_t1/src/main.rs b/difftest/offline_t1/src/main.rs index 0328e2cf3..b79909454 100644 --- a/difftest/offline_t1/src/main.rs +++ b/difftest/offline_t1/src/main.rs @@ -5,12 +5,11 @@ mod json_events; use clap::Parser; use tracing::info; -use common::spike_runner::SpikeRunner; -use common::CommonArgs; +use spike_rs::runner::*; use crate::difftest::Difftest; -fn run_spike(args: &CommonArgs) -> anyhow::Result<()> { +fn run_spike(args: &SpikeArgs) -> anyhow::Result<()> { let mut count: u64 = 0; let spike = SpikeRunner::new(args, true); @@ -32,7 +31,7 @@ fn run_spike(args: &CommonArgs) -> anyhow::Result<()> { fn main() -> anyhow::Result<()> { // parse args - let args = CommonArgs::parse(); + let args = SpikeArgs::parse(); args.setup_logger()?; diff --git a/difftest/offline_t1rocket/Cargo.toml b/difftest/offline_t1rocket/Cargo.toml index 7941021b1..19aa68c01 100644 --- a/difftest/offline_t1rocket/Cargo.toml +++ b/difftest/offline_t1rocket/Cargo.toml @@ -15,5 +15,4 @@ num-bigint = { workspace = true } libloading = "0.8.1" xmas-elf = "0.9.1" -common = { path = "../test_common" } spike_rs = { path = "../spike_rs" } diff --git a/difftest/offline_t1rocket/src/difftest.rs b/difftest/offline_t1rocket/src/difftest.rs index d8ce0a225..2909b8982 100644 --- a/difftest/offline_t1rocket/src/difftest.rs +++ b/difftest/offline_t1rocket/src/difftest.rs @@ -1,29 +1,21 @@ -use common::spike_runner::SpikeRunner; +use spike_rs::spike_runner::{SpikeArgs, SpikeRunner}; use std::path::Path; -use common::rtl_config::RTLConfig; -use common::CommonArgs; - use crate::dut::Dut; use crate::json_events::*; pub struct Difftest { runner: SpikeRunner, dut: Dut, - - #[allow(dead_code)] - config: RTLConfig, } impl Difftest { - pub fn new(args: CommonArgs) -> Self { - let config = RTLConfig { vlen: args.vlen, dlen: args.dlen }; + pub fn new(args: SpikeArgs) -> Self { Self { runner: SpikeRunner::new(&args, true), dut: Dut::new(Path::new( &args.log_file.expect("difftest must be run with a log file"), )), - config, } } diff --git a/difftest/offline_t1rocket/src/dut.rs b/difftest/offline_t1rocket/src/dut.rs index f3e5d20f7..efeaa8d5a 100644 --- a/difftest/offline_t1rocket/src/dut.rs +++ b/difftest/offline_t1rocket/src/dut.rs @@ -1,4 +1,3 @@ -use anyhow::Context; use std::io::BufRead; use std::path::Path; diff --git a/difftest/offline_t1rocket/src/json_events.rs b/difftest/offline_t1rocket/src/json_events.rs index 6a324a37c..bf470a9f8 100644 --- a/difftest/offline_t1rocket/src/json_events.rs +++ b/difftest/offline_t1rocket/src/json_events.rs @@ -1,6 +1,6 @@ -use common::spike_runner::SpikeRunner; use num_bigint::BigUint; use serde::{Deserialize, Deserializer}; +use spike_rs::runner::SpikeRunner; use spike_rs::spike_event::LSU_IDX_DEFAULT; use tracing::{debug, info}; diff --git a/difftest/offline_t1rocket/src/main.rs b/difftest/offline_t1rocket/src/main.rs index c9382462d..1bf119223 100644 --- a/difftest/offline_t1rocket/src/main.rs +++ b/difftest/offline_t1rocket/src/main.rs @@ -5,12 +5,11 @@ mod json_events; use clap::Parser; use tracing::info; -use common::spike_runner::SpikeRunner; -use common::CommonArgs; +use spike_rs::runner::{SpikeArgs, SpikeRunner}; use crate::difftest::Difftest; -fn run_spike(args: &CommonArgs) -> anyhow::Result<()> { +fn run_spike(args: &SpikeArgs) -> anyhow::Result<()> { let mut count: u64 = 0; let spike = SpikeRunner::new(args, true); @@ -32,7 +31,7 @@ fn run_spike(args: &CommonArgs) -> anyhow::Result<()> { fn main() -> anyhow::Result<()> { // parse args - let args = CommonArgs::parse(); + let args = SpikeArgs::parse(); args.setup_logger()?; diff --git a/difftest/spike_rs/Cargo.toml b/difftest/spike_rs/Cargo.toml index 411d44f72..b1dee9f83 100644 --- a/difftest/spike_rs/Cargo.toml +++ b/difftest/spike_rs/Cargo.toml @@ -5,6 +5,9 @@ edition = "2021" [dependencies] anyhow = { workspace = true } +clap = { workspace = true } tracing = { workspace = true } +tracing-subscriber = { workspace = true } + libc = "0.2.155" xmas-elf = "0.9.1" diff --git a/difftest/spike_rs/src/runner.rs b/difftest/spike_rs/src/runner.rs index e5e24407a..5c153453a 100644 --- a/difftest/spike_rs/src/runner.rs +++ b/difftest/spike_rs/src/runner.rs @@ -1,6 +1,8 @@ +use clap::Parser; use std::collections::VecDeque; use std::path::{Path, PathBuf}; -use tracing::debug; +use tracing::{debug, Level}; +use tracing_subscriber::{EnvFilter, FmtSubscriber}; use crate::spike_event::SpikeEvent; use crate::util::load_elf; @@ -32,20 +34,31 @@ pub struct SpikeRunner { pub do_log_vrf: bool, } +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] pub struct SpikeArgs { /// Path to the ELF file + #[arg(long)] pub elf_file: PathBuf, /// Path to the log file + #[arg(long)] pub log_file: Option, + /// Log level: trace, debug, info, warn, error + #[arg(long, default_value = "info")] + pub log_level: String, + /// vlen config + #[arg(long, default_value = env!("DESIGN_VLEN"))] pub vlen: u32, /// dlen config + #[arg(long, default_value = env!("DESIGN_DLEN"))] pub dlen: u32, /// ISA config + #[arg(long, default_value = env!("SPIKE_ISA_STRING"))] pub set: String, } @@ -54,6 +67,23 @@ impl SpikeArgs { let lvl = "M"; Spike::new(&self.set, lvl, (self.dlen / 32) as usize, MEM_SIZE) } + + pub fn setup_logger(&self) -> anyhow::Result<()> { + // setup log + let log_level: Level = self.log_level.parse()?; + let global_logger = FmtSubscriber::builder() + .with_env_filter(EnvFilter::from_default_env()) + .with_max_level(log_level) + .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"); + + Ok(()) + } } pub const MEM_SIZE: usize = 1usize << 32; diff --git a/difftest/test_common/Cargo.toml b/difftest/test_common/Cargo.toml deleted file mode 100644 index d5b3f32aa..000000000 --- a/difftest/test_common/Cargo.toml +++ /dev/null @@ -1,11 +0,0 @@ -[package] -name = "common" -version.workspace = true -edition = "2021" - -[dependencies] -spike_rs = { path = "../spike_rs" } -clap = { workspace = true } -tracing = { workspace = true } -tracing-subscriber = { workspace = true } -anyhow = { workspace = true } diff --git a/difftest/test_common/src/lib.rs b/difftest/test_common/src/lib.rs deleted file mode 100644 index e9690d3a2..000000000 --- a/difftest/test_common/src/lib.rs +++ /dev/null @@ -1,63 +0,0 @@ -use anyhow::Result; -use clap::Parser; -use spike_rs::Spike; -use std::path::PathBuf; -use tracing::Level; -use tracing_subscriber::{EnvFilter, FmtSubscriber}; - -pub mod rtl_config; -pub mod spike_runner; - -#[derive(Parser, Debug)] -#[command(author, version, about, long_about = None)] -pub struct CommonArgs { - /// Path to the ELF file - #[arg(long)] - pub elf_file: PathBuf, - - /// Path to the log file - #[arg(long)] - pub log_file: Option, - - /// Log level: trace, debug, info, warn, error - #[arg(long, default_value = "info")] - pub log_level: String, - - /// vlen config - #[arg(long, default_value = env!("DESIGN_VLEN"))] - pub vlen: u32, - - /// dlen config - #[arg(long, default_value = env!("DESIGN_DLEN"))] - pub dlen: u32, - - /// ISA config - #[arg(long, default_value = env!("SPIKE_ISA_STRING"))] - pub set: String, -} - -pub static MEM_SIZE: usize = 1usize << 32; - -impl CommonArgs { - pub fn to_spike_c_handler(&self) -> Box { - let lvl = "M"; - - Spike::new(&self.set, lvl, (self.dlen / 32) as usize, MEM_SIZE) - } - - pub fn setup_logger(&self) -> Result<()> { - // setup log - let log_level: Level = self.log_level.parse()?; - let global_logger = FmtSubscriber::builder() - .with_env_filter(EnvFilter::from_default_env()) - .with_max_level(log_level) - .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"); - Ok(()) - } -} diff --git a/difftest/test_common/src/rtl_config.rs b/difftest/test_common/src/rtl_config.rs deleted file mode 100644 index 0daf72624..000000000 --- a/difftest/test_common/src/rtl_config.rs +++ /dev/null @@ -1,20 +0,0 @@ -pub struct RTLConfig { - pub vlen: u32, - pub dlen: u32, -} - -// TODO: read from json - -impl RTLConfig { - pub fn xlen(&self) -> u32 { - 32 // TODO: configurable - } - - pub fn vlen_in_bytes(&self) -> u32 { - self.vlen / 8 - } - - pub fn lane_num(&self) -> u32 { - self.dlen / self.xlen() - } -} diff --git a/difftest/test_common/src/spike_runner.rs b/difftest/test_common/src/spike_runner.rs deleted file mode 100644 index ded02898c..000000000 --- a/difftest/test_common/src/spike_runner.rs +++ /dev/null @@ -1,135 +0,0 @@ -use std::collections::VecDeque; -use std::path::Path; -use tracing::debug; - -use spike_rs::spike_event::SpikeEvent; -use spike_rs::util::load_elf; -use spike_rs::Spike; - -use crate::CommonArgs; - -pub struct SpikeRunner { - spike: Box, - - /// commit queue - /// in the spike thread, spike should detech if this queue is full, if not - /// full, execute until a vector instruction, record the behavior of this - /// instruction, and send to commit queue. - /// Note: - /// - The event issued earliest is at the back of the queue - /// - The queue may contain at most one unissued event. If so, the unissued event must be at the - /// front of the queue, and it must be a fence - pub commit_queue: VecDeque, - - /// config for v extension - pub vlen: u32, - pub dlen: u32, - - /// implement the get_t() for mcycle csr update - pub cycle: u64, - - /// for mcycle csr update - pub spike_cycle: u64, - - pub do_log_vrf: bool, -} - -impl SpikeRunner { - pub fn new(args: &CommonArgs, do_log_vrf: bool) -> Self { - // load the elf file - // initialize spike - let mut spike = args.to_spike_c_handler(); - - let entry_addr = load_elf(&mut spike, Path::new(&args.elf_file)).unwrap(); - - // initialize processor - let proc = spike.get_proc(); - let state = proc.get_state(); - proc.reset(); - state.set_pc(entry_addr); - - SpikeRunner { - spike, - commit_queue: VecDeque::new(), - vlen: args.vlen, - dlen: args.dlen, - cycle: 0, - spike_cycle: 0, - do_log_vrf, - } - } - - pub fn load_elf(&mut self, fname: &Path) -> anyhow::Result { - load_elf(&mut *self.spike, fname) - } - - // just execute one instruction for non-difftest - pub fn exec(&self) -> anyhow::Result<()> { - let spike = &self.spike; - let proc = spike.get_proc(); - let state = proc.get_state(); - - let new_pc = proc.func(); - - state.handle_pc(new_pc).unwrap(); - - Ok(()) - } - - // execute the spike processor for one instruction and record - // the spike event for difftest - pub fn spike_step(&mut self) -> SpikeEvent { - let spike = &self.spike; - let proc = self.spike.get_proc(); - let state = proc.get_state(); - - let mcycle = (self.cycle + self.spike_cycle) as usize; - state.set_mcycle(0); - - let mut event = SpikeEvent::new(spike, self.do_log_vrf); - state.clear(); - - let new_pc = if event.is_v() || event.is_exit() { - // inst is v / quit - debug!( - "SpikeStep: spike run vector insn ({}), mcycle={mcycle}", - event.describe_insn(), - ); - event.pre_log_arch_changes(spike, self.vlen).unwrap(); - let new_pc_ = proc.func(); - event.log_arch_changes(spike, self.vlen).unwrap(); - new_pc_ - } else { - // inst is scalar - debug!( - "SpikeStep: spike run scalar insn ({}), mcycle={mcycle}", - event.describe_insn(), - ); - let new_pc_ = proc.func(); - event.log_mem_write(spike).unwrap(); - new_pc_ - }; - - state.handle_pc(new_pc).unwrap(); - - self.spike_cycle += 1; - - event - } - - pub fn find_v_se_to_issue(&mut self) -> SpikeEvent { - if !self.commit_queue.is_empty() && self.commit_queue.front().unwrap().is_vfence() { - // if the front (latest) se is a vfence, return the vfence - self.commit_queue.front().unwrap().clone() - } else { - // else, loop until find a se, and push the se to the front - loop { - let se = self.spike_step(); - if se.is_v() { - self.commit_queue.push_front(se.clone()); - break se.clone(); - } - } - } - } -}