From 518d6ba6dc36cbfa92eb60446c335ba23c49e9cd Mon Sep 17 00:00:00 2001 From: Clo91eaf Date: Sun, 8 Sep 2024 22:34:56 +0800 Subject: [PATCH] [difftest] refactor offline_t1rocket in difftest --- difftest/offline_t1rocket/src/difftest.rs | 2 +- difftest/offline_t1rocket/src/dut.rs | 1 + difftest/spike_rs/src/runner.rs | 78 +++++++++++++++++++++++ difftest/spike_rs/src/spike_event.rs | 68 ++++++++++---------- script/emu/src/Main.scala | 2 +- 5 files changed, 116 insertions(+), 35 deletions(-) diff --git a/difftest/offline_t1rocket/src/difftest.rs b/difftest/offline_t1rocket/src/difftest.rs index 2909b8982..23fd39f24 100644 --- a/difftest/offline_t1rocket/src/difftest.rs +++ b/difftest/offline_t1rocket/src/difftest.rs @@ -1,4 +1,4 @@ -use spike_rs::spike_runner::{SpikeArgs, SpikeRunner}; +use spike_rs::runner::{SpikeArgs, SpikeRunner}; use std::path::Path; use crate::dut::Dut; diff --git a/difftest/offline_t1rocket/src/dut.rs b/difftest/offline_t1rocket/src/dut.rs index efeaa8d5a..f3e5d20f7 100644 --- a/difftest/offline_t1rocket/src/dut.rs +++ b/difftest/offline_t1rocket/src/dut.rs @@ -1,3 +1,4 @@ +use anyhow::Context; use std::io::BufRead; use std::path::Path; diff --git a/difftest/spike_rs/src/runner.rs b/difftest/spike_rs/src/runner.rs index 5c153453a..e96722307 100644 --- a/difftest/spike_rs/src/runner.rs +++ b/difftest/spike_rs/src/runner.rs @@ -21,6 +21,16 @@ pub struct SpikeRunner { /// front of the queue, and it must be a fence pub commit_queue: VecDeque, + /// vector queue to arrange the order of vector instructions, because of the register write + /// dependency, the vector instruction should be issued in order. + pub vector_queue: VecDeque, + + /// scalar queue to arrange the order of scalar reg write instructions + pub scalar_queue: VecDeque, + + /// float queue to arrange the order of scalar freg write instructions + pub float_queue: VecDeque, + /// config for v extension pub vlen: u32, pub dlen: u32, @@ -32,6 +42,11 @@ pub struct SpikeRunner { pub spike_cycle: u64, pub do_log_vrf: bool, + + // register file scoreboard + pub rf_board: Vec>, + // float reg file scoreboard + pub frf_board: Vec>, } #[derive(Parser, Debug)] @@ -105,11 +120,16 @@ impl SpikeRunner { SpikeRunner { spike, commit_queue: VecDeque::new(), + vector_queue: VecDeque::new(), + scalar_queue: VecDeque::new(), + float_queue: VecDeque::new(), vlen: args.vlen, dlen: args.dlen, cycle: 0, spike_cycle: 0, do_log_vrf, + rf_board: vec![None; 32], + frf_board: vec![None; 32], } } @@ -161,6 +181,7 @@ impl SpikeRunner { ); let new_pc_ = proc.func(); event.log_mem_write(spike).unwrap(); + event.log_reg_write(spike).unwrap(); new_pc_ }; @@ -186,4 +207,61 @@ impl SpikeRunner { } } } + + pub fn find_reg_se(&mut self) -> SpikeEvent { + if !self.scalar_queue.is_empty() { + // return the back (oldest) scalar insn + self.scalar_queue.pop_back().unwrap() + } else { + // else, loop until find a se, and push the se to the front + loop { + let se = self.spike_step(); + if se.is_scalar() && se.is_rd_written { + return se; + } else if se.is_scalar() && se.is_fd_written { + self.float_queue.push_front(se.clone()); + } else if se.is_v() { + self.vector_queue.push_front(se.clone()); + } + } + } + } + + pub fn find_freg_se(&mut self) -> SpikeEvent { + if !self.float_queue.is_empty() { + // return the back (oldest) float insn + self.float_queue.pop_back().unwrap() + } else { + // else, loop until find a se, and push the se to the front + loop { + let se = self.spike_step(); + if se.is_scalar() && se.is_rd_written { + self.scalar_queue.push_front(se.clone()); + } else if se.is_scalar() && se.is_fd_written { + return se; + } else if se.is_v() { + self.vector_queue.push_front(se.clone()); + } + } + } + } + + pub fn find_v_se(&mut self) -> SpikeEvent { + if !self.vector_queue.is_empty() { + // return the back (oldest) vector insn + self.vector_queue.pop_back().unwrap() + } else { + // else, loop until find a se, and push the se to the front + loop { + let se = self.spike_step(); + if se.is_scalar() && se.is_rd_written { + self.scalar_queue.push_front(se.clone()); + } else if se.is_scalar() && se.is_fd_written { + self.float_queue.push_front(se.clone()); + } else if se.is_v() { + return se; + } + } + } + } } diff --git a/difftest/spike_rs/src/spike_event.rs b/difftest/spike_rs/src/spike_event.rs index 3487499b2..e05039bea 100644 --- a/difftest/spike_rs/src/spike_event.rs +++ b/difftest/spike_rs/src/spike_event.rs @@ -1,5 +1,5 @@ use std::collections::HashMap; -use tracing::{info, trace}; +use tracing::trace; use Default; use crate::clip; @@ -92,6 +92,7 @@ pub struct SpikeEvent { // mutable states pub is_rd_written: bool, + pub is_fd_written: bool, pub vd_write_record: VdWriteRecord, pub mem_access_record: MemAccessRecord, pub vrf_access_record: VrfAccessRecord, @@ -143,6 +144,7 @@ impl SpikeEvent { rd_bits: Default::default(), is_rd_written: false, + is_fd_written: false, vd_write_record: Default::default(), mem_access_record: Default::default(), vrf_access_record: Default::default(), @@ -326,18 +328,15 @@ impl SpikeEvent { pub fn pre_log_arch_changes(&mut self, spike: &Spike, vlen: u32) -> anyhow::Result<()> { if self.do_log_vrf { - self.rd_bits = spike.get_proc().get_rd(); - // record the vrf writes before executing the insn - let vlen_in_bytes = vlen; - let proc = spike.get_proc(); - let (start, len) = self.get_vrf_write_range(vlen_in_bytes).unwrap(); + self.rd_bits = proc.get_state().get_reg(self.rd_idx, false); + let (start, len) = self.get_vrf_write_range(vlen).unwrap(); self.vd_write_record.vd_bytes.resize(len as usize, 0u8); for i in 0..len { let offset = start + i; - let vreg_index = offset / vlen_in_bytes; - let vreg_offset = offset % vlen_in_bytes; + let vreg_index = offset / vlen; + let vreg_offset = offset % vlen; let cur_byte = proc.get_vreg_data(vreg_index, vreg_offset); self.vd_write_record.vd_bytes[i as usize] = cur_byte; } @@ -391,7 +390,7 @@ impl SpikeEvent { Ok(()) } - fn log_reg_write(&mut self, spike: &Spike) -> anyhow::Result<()> { + pub fn log_reg_write(&mut self, spike: &Spike) -> anyhow::Result<()> { let proc = spike.get_proc(); let state = proc.get_state(); // in spike, log_reg_write is arrange: @@ -402,36 +401,39 @@ impl SpikeEvent { // xx0100 <- csr let reg_write_size = state.get_reg_write_size(); // TODO: refactor it. - (0..reg_write_size).for_each(|idx| match state.get_reg_write_index(idx) & 0xf { - 0b0000 => { - // scalar rf - let data = state.get_reg(self.rd_idx, false); - self.is_rd_written = true; - if data != self.rd_bits { - trace!( - "ScalarRFChange: idx={}, change_from={}, change_to={data}", - self.rd_idx, - self.rd_bits - ); - self.rd_bits = data; + (0..reg_write_size).for_each(|idx| { + let rd_idx_type = state.get_reg_write_index(idx); + match rd_idx_type & 0xf { + 0b0000 => { + // scalar rf + self.rd_idx = rd_idx_type >> 4; + if self.rd_idx != 0 { + let data = state.get_reg(self.rd_idx, false); + self.is_rd_written = true; + self.rd_bits = data; + trace!( + "ScalarRFChange: idx={:#02x}, data={:08x}", + self.rd_idx, + self.rd_bits + ); + } } - } - 0b0001 => { - let data = state.get_reg(self.rd_idx, true); - self.is_rd_written = true; - if data != self.rd_bits { + 0b0001 => { + self.rd_idx = rd_idx_type >> 4; + let data = state.get_reg(self.rd_idx, true); + self.is_fd_written = true; + self.rd_bits = data; trace!( - "FloatRFChange: idx={}, change_from={}, change_to={data}", + "FloatRFChange: idx={:#02x}, data={:08x}", self.rd_idx, self.rd_bits ); - self.rd_bits = data; } + _ => trace!( + "UnknownRegChange, idx={:#02x}, spike detect unknown reg change", + self.rd_idx + ), } - _ => trace!( - "UnknownRegChange, idx={}, spike detect unknown reg change", - state.get_reg_write_index(idx) - ), }); Ok(()) @@ -459,7 +461,7 @@ impl SpikeEvent { trace!("SpikeMemWrite: addr={addr:x}, value={value:x}, size={size}"); if addr == 0x4000_0000 && value == 0xdead_beef { - info!("SpikeExit: exit by writing 0xdeadbeef to 0x40000000"); + trace!("SpikeExit: exit by writing 0xdeadbeef to 0x40000000"); self.is_exit = true; return; diff --git a/script/emu/src/Main.scala b/script/emu/src/Main.scala index 7f328fcfb..3caa63a36 100644 --- a/script/emu/src/Main.scala +++ b/script/emu/src/Main.scala @@ -312,7 +312,7 @@ object Main: val offlineChecker = os.Path( resolveNixPath(s".#t1.${finalConfig}.ip.offline-checker") - ) / "bin" / "offline_t1" + ) / "bin" / (if finalConfig == "t1rocket" then "offline_t1rocket" else "offline_t1") val elfFile = if caseAttr.isDefined then resolveTestElfPath(finalConfig, caseAttr.get).toString