From 81907a5cc6501c004b3007c849932db49ad14702 Mon Sep 17 00:00:00 2001 From: Clo91eaf Date: Thu, 4 Jul 2024 19:37:17 +0800 Subject: [PATCH] [difftest] add timeout check --- difftest/t1-simulator/src/difftest.rs | 64 +++------------------ difftest/t1-simulator/src/difftest/spike.rs | 54 ++++++++++++++++- difftest/t1-simulator/src/main.rs | 22 ++++--- script/emu/src/Main.scala | 2 + 4 files changed, 76 insertions(+), 66 deletions(-) diff --git a/difftest/t1-simulator/src/difftest.rs b/difftest/t1-simulator/src/difftest.rs index da3b2ce41..cfd20fe53 100644 --- a/difftest/t1-simulator/src/difftest.rs +++ b/difftest/t1-simulator/src/difftest.rs @@ -4,7 +4,6 @@ mod spike; use dut::*; pub use spike::SpikeHandle; use std::path::Path; -use tracing::trace; pub struct Difftest { spike: SpikeHandle, @@ -18,72 +17,24 @@ impl Difftest { log_file: String, vlen: u32, dlen: u32, + timeout: usize, set: String, ) -> Self { Self { - spike: SpikeHandle::new(size, Path::new(&elf_file), vlen, dlen, set), + spike: SpikeHandle::new(size, Path::new(&elf_file), vlen, dlen, timeout, set), dut: Dut::new(Path::new(&log_file)), } } - fn peek_issue(&mut self, issue: IssueEvent) -> anyhow::Result<()> { - self.spike.peek_issue(issue).unwrap(); - - Ok(()) - } - - fn update_lsu_idx(&mut self, lsu_enq: LsuEnqEvent) -> anyhow::Result<()> { - self.spike.update_lsu_idx(lsu_enq).unwrap(); - - Ok(()) - } - - fn poke_inst(&mut self) -> anyhow::Result<()> { - loop { - let se = self.spike.find_se_to_issue(); - if (se.is_vfence_insn || se.is_exit_insn) && self.spike.to_rtl_queue.len() == 1 { - if se.is_exit_insn { - return Ok(()); - } - - self.spike.to_rtl_queue.pop_back(); - } else { - break; - } - } - - // TODO: remove these, now just for aligning online difftest - if let Some(se) = self.spike.to_rtl_queue.front() { - // it is ensured there are some other instruction not committed, thus - // se_to_issue should not be issued - if se.is_vfence_insn || se.is_exit_insn { - assert!( - self.spike.to_rtl_queue.len() > 1, - "to_rtl_queue are smaller than expected" - ); - if se.is_exit_insn { - trace!("DPIPokeInst: exit waiting for fence"); - } else { - trace!("DPIPokeInst: waiting for fence, no issuing new instruction"); - } - } else { - trace!( - "DPIPokeInst: poke instruction: pc={:#x}, inst={}", - se.pc, - se.disasm - ); - } - } - Ok(()) - } - pub fn diff(&mut self) -> anyhow::Result<()> { - self.poke_inst().unwrap(); + self.spike.poke_inst().unwrap(); let event = self.dut.step()?; let cycle = event.parameter.cycle.unwrap(); self.spike.cycle = cycle; + self.spike.timeout_check(); + match &*event.event { "memoryWrite" => { let data = event.parameter.data.clone().unwrap(); @@ -100,11 +51,11 @@ impl Difftest { } "issue" => { let idx = event.parameter.idx.unwrap(); - self.peek_issue(IssueEvent { idx, cycle }) + self.spike.peek_issue(IssueEvent { idx, cycle }) } "lsuEnq" => { let enq = event.parameter.enq.unwrap(); - self.update_lsu_idx(LsuEnqEvent { enq, cycle }) + self.spike.update_lsu_idx(LsuEnqEvent { enq, cycle }) } "vrfWriteFromLsu" => { let idx = event.parameter.idx.unwrap(); @@ -190,6 +141,7 @@ impl Difftest { se.record_rd_write(data).unwrap(); se.check_is_ready_for_commit(cycle).unwrap(); + self.spike.last_commit_time = cycle; self.spike.to_rtl_queue.pop_back(); Ok(()) } diff --git a/difftest/t1-simulator/src/difftest/spike.rs b/difftest/t1-simulator/src/difftest/spike.rs index d03e4f866..2665f5a07 100644 --- a/difftest/t1-simulator/src/difftest/spike.rs +++ b/difftest/t1-simulator/src/difftest/spike.rs @@ -116,6 +116,7 @@ pub fn clip(binary: u64, a: i32, b: i32) -> u32 { pub struct Config { pub vlen: u32, pub dlen: u32, + pub timeout: usize, } pub fn add_rtl_write(se: &mut SpikeEvent, vrf_write: VrfWriteEvent, record_idx_base: usize) { @@ -171,10 +172,13 @@ pub struct SpikeHandle { /// for mcycle csr update pub spike_cycle: usize, + + /// timeout check + pub last_commit_time: usize, } impl SpikeHandle { - pub fn new(size: usize, fname: &Path, vlen: u32, dlen: u32, set: String) -> Self { + pub fn new(size: usize, fname: &Path, vlen: u32, dlen: u32, timeout:usize, set: String) -> Self { // register the addr_to_mem callback unsafe { spike_register_callback(rs_addr_to_mem) } @@ -199,9 +203,10 @@ impl SpikeHandle { SpikeHandle { spike, to_rtl_queue: VecDeque::new(), - config: Config { vlen, dlen }, + config: Config { vlen, dlen, timeout }, cycle: 0, spike_cycle: 0, + last_commit_time: 0, } } @@ -439,4 +444,49 @@ impl SpikeHandle { panic!("[{cycle}] cannot find se with instruction source={source}") } + + pub fn poke_inst(&mut self) -> anyhow::Result<()> { + loop { + let se = self.find_se_to_issue(); + if (se.is_vfence_insn || se.is_exit_insn) && self.to_rtl_queue.len() == 1 { + if se.is_exit_insn { + return Ok(()); + } + + self.to_rtl_queue.pop_back(); + } else { + break; + } + } + + // TODO: remove these, now just for aligning online difftest + if let Some(se) = self.to_rtl_queue.front() { + // it is ensured there are some other instruction not committed, thus + // se_to_issue should not be issued + if se.is_vfence_insn || se.is_exit_insn { + assert!( + self.to_rtl_queue.len() > 1, + "to_rtl_queue are smaller than expected" + ); + if se.is_exit_insn { + trace!("DPIPokeInst: exit waiting for fence"); + } else { + trace!("DPIPokeInst: waiting for fence, no issuing new instruction"); + } + } else { + trace!( + "DPIPokeInst: poke instruction: pc={:#x}, inst={}", + se.pc, + se.disasm + ); + } + } + Ok(()) + } + + pub fn timeout_check(&self) { + if self.cycle >= self.config.timeout + self.last_commit_time { + panic!("Simulation timeout, last_commit: {}", self.last_commit_time); + } + } } diff --git a/difftest/t1-simulator/src/main.rs b/difftest/t1-simulator/src/main.rs index 906018f88..8c43cdd7b 100644 --- a/difftest/t1-simulator/src/main.rs +++ b/difftest/t1-simulator/src/main.rs @@ -12,27 +12,31 @@ use tracing_subscriber::{EnvFilter, FmtSubscriber}; #[command(author, version, about, long_about = None)] struct Args { /// Path to the ELF file - #[arg(short, long)] + #[arg(long)] elf_file: String, /// Path to the log file - #[arg(short, long)] + #[arg(long)] log_file: Option, /// Log level: trace, debug, info, warn, error - #[arg(short, long, default_value = "info")] + #[arg(long, default_value = "info")] log_level: String, - /// vlen config (default blastoise 512) - #[arg(short, long)] + /// vlen config + #[arg(long)] vlen: u32, - /// dlen config (default blastoise 256) - #[arg(short, long)] + /// dlen config + #[arg(long)] dlen: u32, + /// timeout config + #[arg(long)] + timeout: usize, + /// ISA config - #[arg(short, long, default_value = "rv32gcv")] + #[arg(long, default_value = "rv32gcv")] set: String, } @@ -44,6 +48,7 @@ fn run_spike(args: Args) -> anyhow::Result<()> { Path::new(&args.elf_file), args.vlen, args.dlen, + args.timeout, args.set, ); loop { @@ -91,6 +96,7 @@ fn main() -> anyhow::Result<()> { args.log_file.unwrap(), args.vlen, args.dlen, + args.timeout, args.set, ); diff --git a/script/emu/src/Main.scala b/script/emu/src/Main.scala index 92088c27c..b84af6f97 100644 --- a/script/emu/src/Main.scala +++ b/script/emu/src/Main.scala @@ -810,6 +810,8 @@ object Main: s"${caseElf}/bin/${caseAttr}.elf", "--log-file", s"${config}-${caseAttr}.event.log", + "--timeout", + "40000", "--log-level", s"${logLevel}" )