Skip to content

Commit

Permalink
[difftest] t1rocketemu: cleanup AXI write
Browse files Browse the repository at this point in the history
  • Loading branch information
FanShupei committed Nov 20, 2024
1 parent 2e2ba34 commit 99d6eee
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 81 deletions.
59 changes: 34 additions & 25 deletions difftest/dpi_t1rocketemu/src/dpi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use dpi_common::plusarg::PlusArgMatcher;
use dpi_common::DpiTarget;
use std::ffi::{c_char, c_longlong};
use svdpi::SvScope;
use tracing::{debug, trace};
use tracing::{debug, info, trace};

use crate::drive::Driver;
use crate::OnlineArgs;
Expand Down Expand Up @@ -33,19 +33,21 @@ unsafe fn fill_axi_read_payload(dst: *mut SvBitVecVal, dlen: u32, payload: &AxiR
}

// Return (strobe in bit, data in byte)
// data_width: AXI width (count in bits)
// size: AXI transaction bytes ( data_width * (1 + MAX_AWLEN) / 8 )
unsafe fn load_from_payload(
payload: &*const SvBitVecVal,
data_width: usize,
size: usize,
data_width: u32,
size: u32,
) -> (Vec<bool>, &[u8]) {
let src = *payload as *mut u8;
let data_width_in_byte = std::cmp::max(size, 4);
let strb_width_per_byte = if data_width < 64 { 4 } else { 8 };
let strb_width_in_byte = size.div_ceil(strb_width_per_byte);
let data_width_in_byte = std::cmp::max(size, 4) as usize;
let strb_width_per_byte = (data_width / 8).min(8) as usize;
let strb_width_in_byte = (size as usize).div_ceil(strb_width_per_byte);

let payload_size_in_byte = strb_width_in_byte + data_width_in_byte; // data width in byte
let byte_vec = std::slice::from_raw_parts(src, payload_size_in_byte);
let strobe = &byte_vec[0..strb_width_in_byte];
let strobe = &byte_vec[..strb_width_in_byte];
let data = &byte_vec[strb_width_in_byte..];

let masks: Vec<bool> = strobe
Expand All @@ -55,18 +57,8 @@ unsafe fn load_from_payload(
mask
})
.collect();
assert_eq!(
masks.len(),
data.len(),
"strobe bit width is not aligned with data byte width"
);

debug!(
"load {payload_size_in_byte} byte from payload: raw_data={} strb={} data={}",
hex::encode(byte_vec),
hex::encode(strobe),
hex::encode(data),
);
assert_eq!(masks.len(), data.len());

(masks, data)
}
Expand Down Expand Up @@ -104,8 +96,10 @@ unsafe extern "C" fn axi_write_highBandwidthAXI(
assert_eq!(data_width as u32, driver.dlen);
assert_eq!(awlen, 0);

let (strobe, data) = load_from_payload(&payload, driver.dlen as usize, (1 << awsize) as usize);
driver.axi_write_high_bandwidth(awaddr as u32, awsize as u64, &strobe, data);
let (strobe, data) = load_from_payload(&payload, driver.dlen, driver.dlen / 8);
driver.axi_write(awaddr as u32, awsize as u32, driver.dlen, &strobe, data);

driver.update_commit_cycle();
});
}

Expand Down Expand Up @@ -171,8 +165,10 @@ unsafe extern "C" fn axi_write_highOutstandingAXI(
assert_eq!(data_width, 32);
assert_eq!(awlen, 0);

let (strobe, data) = load_from_payload(&payload, 32, (1 << awsize) as usize);
driver.axi_write_high_outstanding(awaddr as u32, awsize as u64, &strobe, data);
let (strobe, data) = load_from_payload(&payload, 32, 32 / 8);
driver.axi_write(awaddr as u32, awsize as u32, 32, &strobe, data);

driver.update_commit_cycle();
});
}

Expand Down Expand Up @@ -235,9 +231,22 @@ unsafe extern "C" fn axi_write_loadStoreAXI(
assert_eq!(data_width, 32);
assert_eq!(awlen, 0);

let data_width = if awsize <= 2 { 32 } else { 8 * (1 << awsize) } as usize;
let (strobe, data) = load_from_payload(&payload, data_width, (driver.dlen / 8) as usize);
driver.axi_write_load_store(awaddr as u32, awsize as u64, &strobe, data);
let (strobe, data) = load_from_payload(&payload, 32, 8 * 32 / 8);
let strobe = &strobe[..4];
let data = &data[..4];
driver.axi_write(awaddr as u32, awsize as u32, 32, strobe, data);

driver.update_commit_cycle();

// TODO: move it to MMIO device
if awaddr as u32 == crate::EXIT_POS {
let exit_data = u32::from_le_bytes(data.try_into().expect("slice with incorrect length"));
if exit_data == crate::EXIT_CODE {
info!("driver is ready to quit");
driver.success = true;
driver.quit = true;
}
}
});
}

Expand Down
59 changes: 5 additions & 54 deletions difftest/dpi_t1rocketemu/src/drive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,67 +142,18 @@ impl Driver {
AxiReadPayload { data }
}

pub(crate) fn axi_write_high_bandwidth(
&mut self,
addr: u32,
awsize: u64,
strobe: &[bool],
data: &[u8],
) {
let size = 1 << awsize;
self.shadow_bus.write_mem_axi(addr, size, self.dlen / 8, &strobe, data);
let data_hex = hex::encode(data);
self.last_commit_cycle = get_t();
trace!(
"[{}] axi_write_high_bandwidth (addr={addr:#x}, size={size}, data={data_hex})",
get_t()
);
}

pub(crate) fn axi_write_high_outstanding(
&mut self,
addr: u32,
awsize: u64,
strobe: &[bool],
data: &[u8],
) {
let size = 1 << awsize;
self.shadow_bus.write_mem_axi(addr, size, 4, strobe, data);
let data_hex = hex::encode(data);
self.last_commit_cycle = get_t();
trace!(
"[{}] axi_write_high_outstanding (addr={addr:#x}, size={size}, data={data_hex})",
get_t()
);
}

pub(crate) fn axi_write_load_store(
// data_width: AXI width (count in bits)
pub(crate) fn axi_write(
&mut self,
addr: u32,
awsize: u64,
awsize: u32,
data_width: u32,
strobe: &[bool],
data: &[u8],
) {
let bus_size = data_width / 8;
let size = 1 << awsize;
let bus_size = if size == 32 { 32 } else { 4 };
self.shadow_bus.write_mem_axi(addr, size, bus_size, strobe, data);
let data_hex = hex::encode(data);
self.last_commit_cycle = get_t();

trace!(
"[{}] axi_write_load_store (addr={addr:#x}, size={size}, data={data_hex})",
get_t()
);

// check exit with code
if addr == EXIT_POS {
let exit_data_slice = data[..4].try_into().expect("slice with incorrect length");
if u32::from_le_bytes(exit_data_slice) == EXIT_CODE {
info!("driver is ready to quit");
self.success = true;
self.quit = true;
}
}
}

pub(crate) fn watchdog(&mut self) -> u8 {
Expand Down
4 changes: 2 additions & 2 deletions difftest/dpi_t1rocketemu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ impl OnlineArgs {
}

// quit signal
const EXIT_POS: u32 = 0x4000_0000;
const EXIT_CODE: u32 = 0xdead_beef;
pub const EXIT_POS: u32 = 0x4000_0000;
pub const EXIT_CODE: u32 = 0xdead_beef;

// keep in sync with TestBench.ClockGen
// the value is measured in simulation time unit
Expand Down

0 comments on commit 99d6eee

Please sign in to comment.