Skip to content

Commit

Permalink
[difftest] refactor spike event's type and refactor driver issue logic
Browse files Browse the repository at this point in the history
  • Loading branch information
Clo91eaf committed Jul 17, 2024
1 parent 2e21ad0 commit 3893c36
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 104 deletions.
70 changes: 31 additions & 39 deletions difftest/online_drive/src/drive.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use common::spike_runner::SpikeRunner;
use common::MEM_SIZE;
use spike_rs::spike_event::MemAccessRecord;
use spike_rs::spike_event::{SpikeEvent, SpikeEventType};
use spike_rs::spike_event::SpikeEvent;
use spike_rs::util::load_elf_to_buffer;
use tracing::{debug, error, info, trace};

Expand Down Expand Up @@ -152,7 +152,7 @@ impl Driver {
let size = 1 << arsize;
let data = self.read_mem(addr, size, self.dlen / 8);
let data_hex = hex::encode(&data);
info!(
trace!(
"[{}] axi_read_high_bandwidth (addr={addr:#x}, size={size}, data={data_hex})",
get_t()
);
Expand All @@ -170,7 +170,7 @@ impl Driver {

self.write_mem(addr, self.dlen / 8, &strobe, data);
let data_hex = hex::encode(data);
info!(
trace!(
"[{}] axi_write_high_bandwidth (addr={addr:#x}, size={size}, data={data_hex})",
get_t()
);
Expand All @@ -181,7 +181,7 @@ impl Driver {
assert!(size <= 4);
let data = self.read_mem(addr, size, 4);
let data_hex = hex::encode(&data);
info!(
trace!(
"[{}] axi_read_indexed (addr={addr:#x}, size={size}, data={data_hex})",
get_t()
);
Expand All @@ -198,7 +198,7 @@ impl Driver {
let size = 1 << awsize;
self.write_mem(addr, 4, strobe, data);
let data_hex = hex::encode(data);
info!(
trace!(
"[{}] axi_write_high_bandwidth (addr={addr:#x}, size={size}, data={data_hex})",
get_t()
);
Expand Down Expand Up @@ -240,37 +240,20 @@ impl Driver {
}

pub(crate) fn step(&mut self) -> SpikeEvent {
// there will be a vfence/load/store in the commit queue
// there will be a vfence / scalar load / scalar store in the commit queue's front
if let Some(se) = self.spike_runner.commit_queue.front() {
let is_vfence = se.is_vfence();
let is_load_or_store = se.is_load() || se.is_store();
if is_vfence || (is_load_or_store && self.vector_lsu_count != 0) {
// if the front (latest) se is a vfence/load/store, return
if se.is_vfence() || se.is_load() || se.is_store() {
return se.clone();
}
}

loop {
// step until the instruction is a vector / exit / scalar load / scalar store
// push into the commit queue and return
let se = self.spike_runner.spike_step();
match se.typ {
SpikeEventType::Vector | SpikeEventType::QUIT => {
// if the instruction is a vector store/load, increment the vector_lsu_count
if se.is_vload() || se.is_vstore() {
self.vector_lsu_count += 1;
}
self.spike_runner.commit_queue.push_front(se.clone());
return se;
}
SpikeEventType::Scalar => {
if se.is_load() || se.is_store() {
if self.vector_lsu_count == 0 {
self.apply_to_shadow_mem(&se.mem_access_record);
} else {
self.spike_runner.commit_queue.push_front(se.clone());
return se;
}
}
}
if se.is_v() || se.is_vfence() || se.is_load() || se.is_store() {
self.spike_runner.commit_queue.push_front(se.clone());
return se;
}
}
}
Expand Down Expand Up @@ -304,7 +287,13 @@ impl Driver {
}
} else if se.is_load() || se.is_store() {
// scalar load / scalar store
info!(
"issue scalar ({}), count={}",
if se.is_load() { "load" } else { "store" },
self.vector_lsu_count
);
if self.vector_lsu_count == 0 {
// issue scalar load / store
self.apply_to_shadow_mem(&se.mem_access_record);
self.spike_runner.commit_queue.pop_front();
self.issue_instruction() // pop and push a new one
Expand All @@ -313,7 +302,16 @@ impl Driver {
}
} else {
// vector
info!("[{}] issuing ({})", get_t(), se.describe_insn());
if se.is_vload() || se.is_vstore() {
self.vector_lsu_count += 1;
}

info!(
"[{}] issue vector ({}), count={} ",
get_t(),
se.describe_insn(),
self.vector_lsu_count,
);
self.issued += 1;

IssueData {
Expand All @@ -330,18 +328,11 @@ impl Driver {
}

pub(crate) fn retire_instruction(&mut self, _: &Retire) {
let se_to_retire = self.spike_runner.commit_queue.back().unwrap();
info!(
"[{}] retire_instruction {} (pc={:08x}, bits={:08x})",
get_t(),
se_to_retire.disasm,
se_to_retire.pc,
se_to_retire.inst_bits,
);
let se = self.spike_runner.commit_queue.back().unwrap();

// we make a copy of mem_access_record to circumvent the borrow checker
// todo: filter all vector instruction.
let mem_access_record = se_to_retire.mem_access_record.to_owned();
let mem_access_record = se.mem_access_record.to_owned();
self.apply_to_shadow_mem(&mem_access_record);

self.spike_runner.commit_queue.pop_back();
Expand All @@ -350,5 +341,6 @@ impl Driver {

pub(crate) fn retire_memory(&mut self) {
self.vector_lsu_count -= 1;
info!("[{}] retire, count={}", get_t(), self.vector_lsu_count);
}
}
60 changes: 24 additions & 36 deletions difftest/spike_rs/src/spike_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,6 @@ pub struct VrfAccessRecord {
pub const LSU_IDX_DEFAULT: u8 = 0xff;
pub const ISSUE_IDX_DEFAULT: u8 = 0xff;

#[derive(Debug, Clone)]
pub enum SpikeEventType {
Scalar,
Vector,
QUIT,
}

impl Default for SpikeEventType {
fn default() -> Self {
SpikeEventType::Scalar
}
}

#[derive(Default, Debug, Clone)]
pub struct SpikeEvent {
pub do_log_vrf: bool,
Expand All @@ -88,7 +75,6 @@ pub struct SpikeEvent {
pub rs1_bits: u32,
pub rs2_bits: u32,
pub rd_idx: u32,
pub typ: SpikeEventType,

// vtype
pub vtype: u32,
Expand Down Expand Up @@ -119,29 +105,9 @@ impl SpikeEvent {

let opcode = clip(inst_bits, 0, 6);
let width = clip(inst_bits, 12, 14);
let rs1 = clip(inst_bits, 15, 19);
let csr = clip(inst_bits, 20, 31);

let is_rs_fp = opcode == 0b1010111 && width == 0b101/* OPFVF */;

// early return vsetvl scalar instruction
let is_vsetvl = opcode == 0b1010111 && width == 0b111;

let is_load_type = opcode == 0b0000111 && (width.wrapping_sub(1) & 0b100 != 0);
let is_store_type = opcode == 0b0100111 && (width.wrapping_sub(1) & 0b100 != 0);
let is_v_type = opcode == 0b1010111;

let is_csr_type = opcode == 0b1110011 && ((width & 0b011) != 0);
let is_csr_write = is_csr_type && (((width & 0b100) | rs1) != 0);

let is_quit = is_csr_write && csr == 0x7cc;

let typ = match (is_vsetvl, is_load_type | is_store_type | is_v_type, is_quit) {
(true, false, false) => SpikeEventType::Scalar,
(false, true, false) => SpikeEventType::Vector,
(false, false, true) => SpikeEventType::QUIT,
_ => SpikeEventType::Scalar,
};

// rs1, rs2
let (rs1, rs2) = (proc.get_rs1(), proc.get_rs2());
Expand Down Expand Up @@ -172,7 +138,6 @@ impl SpikeEvent {
vstart: proc.vu_get_vstart(),

rd_bits: Default::default(),
typ,

is_rd_written: false,
vd_write_record: Default::default(),
Expand All @@ -189,6 +154,14 @@ impl SpikeEvent {
clip(self.inst_bits, 12, 14)
}

pub fn rs1(&self) -> u32 {
clip(self.inst_bits, 15, 19)
}

pub fn csr(&self) -> u32 {
clip(self.inst_bits, 20, 31)
}

pub fn funct6(&self) -> u32 {
clip(self.inst_bits, 26, 31)
}
Expand All @@ -215,6 +188,18 @@ impl SpikeEvent {
self.opcode() == 0b0100111 && self.width().wrapping_sub(1) & 0b100 != 0
}

pub fn is_v(&self) -> bool {
(self.opcode() == 0b1010111 || self.is_vload() || self.is_vstore()) && !self.is_vsetvl()
}

pub fn is_vsetvl(&self) -> bool {
self.opcode() == 0b1010111 && self.width() == 0b111
}

pub fn is_scalar(&self) -> bool {
!self.is_v()
}

// check whether the instruction is a scalar load
pub fn is_load(&self) -> bool {
self.opcode() == 0b0000011
Expand All @@ -238,7 +223,10 @@ impl SpikeEvent {
}

pub fn is_exit(&self) -> bool {
self.opcode() == 0b1110011
let is_csr_type = self.opcode() == 0b1110011 && ((self.width() & 0b011) != 0);
let is_csr_write = is_csr_type && (((self.width() & 0b100) | self.rs1()) != 0);

is_csr_write && self.csr() == 0x7cc
}

pub fn is_vfence(&self) -> bool {
Expand Down
53 changes: 24 additions & 29 deletions difftest/test_common/src/spike_runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::VecDeque;
use std::path::Path;
use tracing::debug;

use spike_rs::spike_event::{SpikeEvent, SpikeEventType};
use spike_rs::spike_event::SpikeEvent;
use spike_rs::util::load_elf;
use spike_rs::Spike;

Expand Down Expand Up @@ -98,28 +98,26 @@ impl SpikeRunner {
let mut event = SpikeEvent::new(spike, self.do_log_vrf);
state.clear();

let new_pc = match event.typ {
// inst is load / store / v / quit
SpikeEventType::Vector | SpikeEventType::QUIT => {
debug!(
"SpikeStep: spike run vector insn ({}), is_vfence={}",
event.describe_insn(),
event.is_vfence(),
);
event.pre_log_arch_changes(spike, self.vlen).unwrap();
let new_pc_ = proc.func();
event.log_arch_changes(spike, self.vlen).unwrap();
new_pc_
}
SpikeEventType::Scalar => {
debug!(
"SpikeStep: spike run scalar insn (pc={:#x}, disasm={}, bits={:#x})",
pc, disasm, insn_bits,
);
let new_pc_ = proc.func();
event.log_mem_write(spike).unwrap();
new_pc_
}
let new_pc = if event.is_v() || event.is_exit() {
// inst is v / quit
debug!(
"SpikeStep: spike run vector insn ({}), is_vfence={}",
event.describe_insn(),
event.is_vfence(),
);
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 (pc={:#x}, disasm={}, bits={:#x})",
pc, disasm, insn_bits,
);
let new_pc_ = proc.func();
event.log_mem_write(spike).unwrap();
new_pc_
};

state.handle_pc(new_pc).unwrap();
Expand All @@ -137,12 +135,9 @@ impl SpikeRunner {
// else, loop until find a se, and push the se to the front
loop {
let se = self.spike_step();
match se.typ {
SpikeEventType::Vector | SpikeEventType::QUIT => {
self.commit_queue.push_front(se.clone());
break se.clone();
}
SpikeEventType::Scalar => {}
if se.is_v() {
self.commit_queue.push_front(se.clone());
break se.clone();
}
}
}
Expand Down

0 comments on commit 3893c36

Please sign in to comment.