From 3d7a1538fd0cd7d40b10c8499cfc35f44e6e33af Mon Sep 17 00:00:00 2001 From: Shupei Fan Date: Tue, 26 Nov 2024 14:09:24 +0000 Subject: [PATCH] [difftest] t1rocketemu: cleanup & remove bus --- difftest/dpi_t1emu/src/dpi.rs | 4 +- difftest/dpi_t1emu/src/drive.rs | 1 + difftest/dpi_t1rocketemu/src/bus.rs | 167 ------------------ difftest/dpi_t1rocketemu/src/bus/disp.rs | 138 --------------- difftest/dpi_t1rocketemu/src/bus/mem.rs | 40 ----- difftest/dpi_t1rocketemu/src/dpi.rs | 4 +- difftest/dpi_t1rocketemu/src/drive.rs | 8 +- .../src/interconnect/framebuffer.rs | 2 - difftest/dpi_t1rocketemu/src/lib.rs | 5 +- 9 files changed, 10 insertions(+), 359 deletions(-) delete mode 100644 difftest/dpi_t1rocketemu/src/bus.rs delete mode 100644 difftest/dpi_t1rocketemu/src/bus/disp.rs delete mode 100644 difftest/dpi_t1rocketemu/src/bus/mem.rs diff --git a/difftest/dpi_t1emu/src/dpi.rs b/difftest/dpi_t1emu/src/dpi.rs index 9ee11666a..cf89f7ba3 100644 --- a/difftest/dpi_t1emu/src/dpi.rs +++ b/difftest/dpi_t1emu/src/dpi.rs @@ -3,8 +3,8 @@ use dpi_common::plusarg::PlusArgMatcher; use dpi_common::DpiTarget; -use std::ffi::{c_char, c_longlong}; -use tracing::{debug, error}; +use std::ffi::c_longlong; +use tracing::debug; use crate::drive::Driver; use crate::OnlineArgs; diff --git a/difftest/dpi_t1emu/src/drive.rs b/difftest/dpi_t1emu/src/drive.rs index ce9b71067..45ac99794 100644 --- a/difftest/dpi_t1emu/src/drive.rs +++ b/difftest/dpi_t1emu/src/drive.rs @@ -99,6 +99,7 @@ pub(crate) struct Driver { spike_runner: SpikeRunner, // SvScope from t1_cosim_init + #[allow(unused)] scope: SvScope, pub(crate) success: bool, diff --git a/difftest/dpi_t1rocketemu/src/bus.rs b/difftest/dpi_t1rocketemu/src/bus.rs deleted file mode 100644 index 9f5a3aa59..000000000 --- a/difftest/dpi_t1rocketemu/src/bus.rs +++ /dev/null @@ -1,167 +0,0 @@ -mod disp; -mod mem; - -use disp::*; -use mem::*; -use tracing::{debug, error, trace}; - -trait ShadowDevice: Send + Sync { - fn new() -> Box - where - Self: Sized; - /// addr: offset respect to the base of this device - fn read_mem(&self, addr: usize, size: usize) -> Vec; - /// addr: offset respect to the base of this device - fn write_mem(&mut self, addr: usize, data: u8); - /// addr: offset respect to the base of this device - /// strobe: signals which element in data is valid, None = all valid - fn write_mem_chunk(&mut self, addr: usize, size: usize, strobe: Option<&[bool]>, data: &[u8]); -} - -struct ShadowBusDevice { - base: usize, - size: usize, - device: Box, -} - -const MAX_DEVICES: usize = 4; - -pub(crate) struct ShadowBus { - devices: [ShadowBusDevice; MAX_DEVICES], -} - -impl ShadowBus { - /// Initiate the devices on the bus as specified in `tests/t1.ld` - /// NOTE: For some reason DDR is not aligned in the address space - pub fn new() -> Self { - const DDR_SIZE: usize = 0x80000000; - const SCALAR_SIZE: usize = 0x20000000; - const SRAM_SIZE: usize = 0x00400000; - - Self { - devices: [ - ShadowBusDevice { - base: 0x04000000, - size: 0x02000000, - device: DisplayDevice::new(), - }, - ShadowBusDevice { - base: 0x20000000, - size: SCALAR_SIZE, - device: MemDevice::::new(), - }, - ShadowBusDevice { - base: 0x40000000, - size: DDR_SIZE, - device: MemDevice::::new(), - }, - ShadowBusDevice { - base: 0xc0000000, - size: SRAM_SIZE, - device: MemDevice::::new(), - }, - ], - } - } - - // size: 1 << arsize - // bus_size: AXI bus width in bytes - // return: Vec with len=bus_size - // if size < bus_size, the result is padded due to AXI narrow transfer rules - pub fn read_mem_axi(&self, addr: u32, size: u32, bus_size: u32) -> Vec { - assert!( - addr % size == 0 && bus_size % size == 0, - "unaligned access addr={addr:#x} size={size}B dlen={bus_size}B" - ); - - let start = addr as usize; - let end = (addr + size) as usize; - - let handler = self.devices.iter().find(|d| match d { - ShadowBusDevice { base, size, device: _ } => *base <= start && end <= (*base + *size), - }); - - match handler { - Some(ShadowBusDevice { base, size: _, device }) => { - let offset = start - *base; - let data = device.read_mem(offset, size as usize); - - if size < bus_size { - let mut data_padded = vec![0; bus_size as usize]; - let start = (addr % bus_size) as usize; - let end = start + data.len(); - data_padded[start..end].copy_from_slice(&data); - - data_padded - } else { - data - } - } - None => { - panic!("read addr={addr:#x} size={size}B dlen={bus_size}B leads to nowhere!"); - vec![0; bus_size as usize] - } - } - } - - // size: 1 << awsize - // bus_size: AXI bus width in bytes - // masks: write strobes, len=bus_size - // data: write data, len=bus_size - pub fn write_mem_axi( - &mut self, - addr: u32, - size: u32, - bus_size: u32, - masks: &[bool], - data: &[u8], - ) { - assert!( - addr % size == 0 && bus_size % size == 0, - "unaligned write access addr={addr:#x} size={size}B dlen={bus_size}B" - ); - - if !masks.iter().any(|x| *x) { - trace!("Mask 0 write detected"); - return; - } - - let start = (addr & ((!bus_size) + 1)) as usize; - let end = start + bus_size as usize; - - let handler = self.devices.iter_mut().find(|d| match d { - ShadowBusDevice { base, size, device: _ } => *base <= start && end <= (*base + *size), - }); - - match handler { - Some(ShadowBusDevice { base, size: _, device }) => { - let offset = start - *base; - device.write_mem_chunk(offset, bus_size as usize, Option::from(masks), data); - } - None => { - panic!("write addr={addr:#x} size={size}B dlen={bus_size}B leads to nowhere!"); - } - } - } - - pub fn load_mem_seg(&mut self, vaddr: usize, data: &[u8]) { - let handler = self - .devices - .iter_mut() - .find(|d| match d { - ShadowBusDevice { base, size, device: _ } => { - *base <= vaddr as usize && (vaddr as usize + data.len()) <= (*base + *size) - } - }) - .unwrap_or_else(|| { - panic!( - "fail reading ELF into mem with vaddr={:#x}, len={}B: load memory to nowhere", - vaddr, - data.len() - ) - }); - - let offset = vaddr - handler.base; - handler.device.write_mem_chunk(offset, data.len(), None, data) - } -} diff --git a/difftest/dpi_t1rocketemu/src/bus/disp.rs b/difftest/dpi_t1rocketemu/src/bus/disp.rs deleted file mode 100644 index 11bb8026c..000000000 --- a/difftest/dpi_t1rocketemu/src/bus/disp.rs +++ /dev/null @@ -1,138 +0,0 @@ -use super::ShadowDevice; -use std::fs::File; -use std::io::BufWriter; -use std::path::PathBuf; - -/// Device memory layout: -/// `0x000_0000 - 0x1FF_0000` addressable frame buffer memory -/// Picture is in packed RGB24 layout, row-major. See tests/disp/simple for example. -/// OUTPUT_WIDTH * OUTPUT_HEIGHT writable, out-of-range writes will be ignored -/// `0x1FF_0000 - 0x200_0000` control registers -/// `0x1FF_0000`: read as frame counter, write to flush frame buffer as png -/// `0x1FF_0004`: output dimensions -/// 0x04-06 16bits: OUTPUT_WIDTH (currently fixed at 960) -/// 0x06-08 16bits: OUTPUT_HEIGHT (currently fixed at 720) -/// TODO: configurable dimension and color depth support? -/// TODO: behavior emulation closer to actual LCD display? -pub(super) struct DisplayDevice { - vram: Vec, - frame_counter: i32, -} - -const DISPLAY_WIDTH: u32 = 960; -const DISPLAY_HEIGHT: u32 = 720; - -const REG_START: usize = 0x1FF0000; -const REG_FLUSH: usize = 0x1FF0000; -const REG_DIM: usize = 0x1FF0020; - -impl ShadowDevice for DisplayDevice { - fn new() -> Box - where - Self: Sized, - { - Box::new(Self { - vram: vec![0u8; (DISPLAY_WIDTH * DISPLAY_HEIGHT * 3) as usize], - frame_counter: 0, - }) - } - - fn read_mem(&self, addr: usize, size: usize) -> Vec { - let start = addr; - let end = addr + size; - - assert!( - !(start < REG_START && end > REG_START), - "Read burst should not cross register boundary" - ); - - if start < REG_START { - self.vram_read(addr, size) - } else { - self.reg_read(addr - REG_START, size) - } - } - - fn write_mem(&mut self, addr: usize, data: u8) { - if addr < self.vram.len() { - self.vram[addr] = data; - } else if addr == REG_FLUSH { - self.encode_png().unwrap(); - self.frame_counter += 1; - } - } - - fn write_mem_chunk(&mut self, addr: usize, size: usize, strobe: Option<&[bool]>, data: &[u8]) { - let start = addr; - let end = addr + size; - - if end <= self.vram.len() { - if let Some(masks) = strobe { - masks.iter().enumerate().for_each(|(i, mask)| { - if *mask { - self.vram[addr + i] = data[i]; - } - }) - } else { - let start = addr; - let end = addr + size; - self.vram[start..end].copy_from_slice(data); - } - } else { - if let Some(masks) = strobe { - masks.iter().enumerate().for_each(|(i, mask)| { - if *mask { - self.write_mem(addr + i, data[i]); - } - }) - } else { - for i in start..end { - self.write_mem(addr + i, data[i]); - } - } - } - } -} - -impl DisplayDevice { - fn vram_read(&self, offset: usize, size: usize) -> Vec { - let mut buffer = vec![0u8; size]; - let start = std::cmp::min(self.vram.len(), offset); - let end = std::cmp::min(self.vram.len(), offset + size); - (&mut buffer[0..(start - end)]).copy_from_slice(&self.vram[start..end]); - buffer - } - - fn reg_read(&self, offset: usize, size: usize) -> Vec { - let mut buffer = vec![0u8; size]; - let counter = self.frame_counter.to_le_bytes().into_iter(); - let width = (DISPLAY_WIDTH as u16).to_le_bytes().into_iter(); - let height = (DISPLAY_HEIGHT as u16).to_le_bytes().into_iter(); - let reg_space: Vec = counter.chain(width).chain(height).collect(); - - let start = std::cmp::min(reg_space.len(), offset); - let end = std::cmp::min(reg_space.len(), offset + size); - (&mut buffer[0..(end - start)]).copy_from_slice(®_space[start..end]); - buffer - } - - fn encode_png(&self) -> anyhow::Result<()> { - let out_dir = PathBuf::from( - std::env::var("DISP_OUT_DIR").unwrap_or("./t1-sim-result/result/pngs".to_string()), - ); - std::fs::create_dir_all(&out_dir)?; - - let path = out_dir.join(format!("frame_{}.png", self.frame_counter)); - let file = File::create(path)?; - let ref mut w = BufWriter::new(file); - - let mut encoder = png::Encoder::new(w, DISPLAY_WIDTH, DISPLAY_HEIGHT); - encoder.set_color(png::ColorType::Rgb); - encoder.set_depth(png::BitDepth::Eight); - encoder.set_srgb(png::SrgbRenderingIntent::Perceptual); - - let mut writer = encoder.write_header()?; - writer.write_image_data(&self.vram)?; - Ok(()) - } -} diff --git a/difftest/dpi_t1rocketemu/src/bus/mem.rs b/difftest/dpi_t1rocketemu/src/bus/mem.rs deleted file mode 100644 index 5c8eb474a..000000000 --- a/difftest/dpi_t1rocketemu/src/bus/mem.rs +++ /dev/null @@ -1,40 +0,0 @@ -use super::ShadowDevice; - -pub(super) struct MemDevice { - mem: Box<[u8; SIZE]>, -} - -impl ShadowDevice for MemDevice { - fn new() -> Box - where - Self: Sized, - { - Box::new(Self { mem: vec![0u8; SIZE].try_into().unwrap() }) - } - - fn read_mem(&self, addr: usize, size: usize) -> Vec { - let start = addr; - let end = addr + size; - self.mem[start..end].to_vec() - } - - fn write_mem(&mut self, addr: usize, data: u8) { - self.mem[addr] = data; - } - - fn write_mem_chunk(&mut self, addr: usize, size: usize, strobe: Option<&[bool]>, data: &[u8]) { - // NOTE: addr & size alignment check already done in ShadowBus, and ELF load can be unaligned anyway. - - if let Some(masks) = strobe { - masks.iter().enumerate().for_each(|(i, mask)| { - if *mask { - self.mem[addr + i] = data[i]; - } - }) - } else { - let start = addr; - let end = addr + size; - self.mem[start..end].copy_from_slice(data); - } - } -} diff --git a/difftest/dpi_t1rocketemu/src/dpi.rs b/difftest/dpi_t1rocketemu/src/dpi.rs index 65964d9c2..8072a9e1a 100644 --- a/difftest/dpi_t1rocketemu/src/dpi.rs +++ b/difftest/dpi_t1rocketemu/src/dpi.rs @@ -3,9 +3,9 @@ use dpi_common::plusarg::PlusArgMatcher; use dpi_common::DpiTarget; -use std::ffi::{c_char, c_longlong}; +use std::ffi::c_longlong; use svdpi::SvScope; -use tracing::{debug, info, trace}; +use tracing::{debug, info}; use crate::drive::Driver; use crate::OnlineArgs; diff --git a/difftest/dpi_t1rocketemu/src/drive.rs b/difftest/dpi_t1rocketemu/src/drive.rs index 8472aaad4..5e2774f38 100644 --- a/difftest/dpi_t1rocketemu/src/drive.rs +++ b/difftest/dpi_t1rocketemu/src/drive.rs @@ -1,8 +1,6 @@ -use crate::bus::ShadowBus; -use crate::dpi::*; +use crate::get_t; use crate::interconnect::{create_emu_addrspace, AddressSpace}; use crate::OnlineArgs; -use crate::{get_t, EXIT_CODE, EXIT_POS}; use svdpi::SvScope; use anyhow::Context; @@ -12,10 +10,9 @@ use elf::{ ElfStream, }; use std::collections::HashMap; -use std::ops::Add; use std::os::unix::fs::FileExt; use std::{fs, path::Path}; -use tracing::{debug, error, info, trace}; +use tracing::{debug, error, trace}; #[derive(Debug)] #[allow(dead_code)] @@ -29,6 +26,7 @@ pub type FunctionSymTab = HashMap; pub(crate) struct Driver { // SvScope from t1rocket_cosim_init + #[allow(unused)] scope: SvScope, pub(crate) dlen: u32, diff --git a/difftest/dpi_t1rocketemu/src/interconnect/framebuffer.rs b/difftest/dpi_t1rocketemu/src/interconnect/framebuffer.rs index de38850f4..876055314 100644 --- a/difftest/dpi_t1rocketemu/src/interconnect/framebuffer.rs +++ b/difftest/dpi_t1rocketemu/src/interconnect/framebuffer.rs @@ -24,8 +24,6 @@ const DISPLAY_WIDTH: u32 = 960; const DISPLAY_HEIGHT: u32 = 720; const REG_START: u32 = 0x1FF0000; -const REG_FLUSH: usize = 0x1FF0000; -const REG_DIM: usize = 0x1FF0020; impl FrameBuffer { pub fn new() -> Self { diff --git a/difftest/dpi_t1rocketemu/src/lib.rs b/difftest/dpi_t1rocketemu/src/lib.rs index 914013351..447f4a03d 100644 --- a/difftest/dpi_t1rocketemu/src/lib.rs +++ b/difftest/dpi_t1rocketemu/src/lib.rs @@ -2,9 +2,8 @@ use std::path::PathBuf; use dpi_common::plusarg::PlusArgMatcher; -mod bus; -pub mod dpi; -pub mod drive; +mod dpi; +mod drive; mod interconnect; pub(crate) struct OnlineArgs {