diff --git a/src/main.rs b/src/main.rs index cf7e8cd..dcbe97f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,11 @@ use core::{ panic::PanicInfo, sync::atomic::{self, Ordering}, }; -use pim::{array::PimArray, config::PimConfig, kernel::NOP_KERNEL}; +use pim::{ + array::PimArray, + config::PimConfig, + kernel::{NOP_KERNEL, TEST_KERNEL}, +}; use uart::Uart0; mod m5ops; @@ -21,50 +25,50 @@ static mut TEST_ARRAY: PimArray = PimArray([0; 256]); #[no_mangle] pub extern "C" fn entry() -> ! { let mut pim_config = pim::config::PimConfig { - bank_mode: pim::config::BankMode::AllBank, - kernel: NOP_KERNEL, + bank_mode: pim::config::BankMode::PimAllBank, + kernel: TEST_KERNEL, }; let mut pim_writer = pim::config::PimWriter; let mut uart = Uart0 {}; unsafe { - // Toggle AllBank - pim_writer.write( - serde_json_core::to_string::(&pim_config) - .unwrap() - .as_str(), - ); + writeln!( + &mut uart, + "PIM array is at {:x?}", + core::ptr::addr_of!(TEST_ARRAY) + ) + .unwrap(); + writeln!(&mut uart, "Read from all banks").unwrap(); - writeln!(&mut uart, "Enable AllBank").unwrap(); - - writeln!(&mut uart, "Write single cache line").unwrap(); - TEST_ARRAY.0[0] = 0xaa; - TEST_ARRAY.0[1] = 0xaa; - TEST_ARRAY.0[2] = 0xaa; - TEST_ARRAY.0[3] = 0xaa; - TEST_ARRAY.0[4] = 0xaa; - TEST_ARRAY.0[5] = 0xaa; - TEST_ARRAY.0[6] = 0xaa; - TEST_ARRAY.0[7] = 0xaa; - - // Flush and invalidate array + // Invalidate array just in case for element in TEST_ARRAY.0.iter().step_by(8) { - asm!("dc civac, {val}", val = in(reg) element); + asm!("dc ivac, {val}", val = in(reg) element); } - // Wait on all flushes to complete - asm!("dsb sy"); - - // Toggle AllBank - pim_config.bank_mode = pim::config::BankMode::SingleBank; pim_writer.write( - serde_json_core::to_string::(&pim_config) + serde_json_core::to_string::(&pim_config) .unwrap() .as_str(), ); - writeln!(&mut uart, "Disable AllBank").unwrap(); - // Print array + // Fetch single cache line in array + core::ptr::read_volatile(&TEST_ARRAY.0[0]); + core::ptr::read_volatile(&TEST_ARRAY.0[8]); + + asm!("dsb sy"); + + pim_config.bank_mode = pim::config::BankMode::SingleBank; + pim_writer.write( + serde_json_core::to_string::(&pim_config) + .unwrap() + .as_str(), + ); + + // Invalidate array + for element in TEST_ARRAY.0.iter().step_by(8) { + asm!("dc ivac, {val}", val = in(reg) element); + } + writeln!( &mut uart, "{:?}: {:x?}", diff --git a/src/pim/config.rs b/src/pim/config.rs index e719d83..71ac50d 100644 --- a/src/pim/config.rs +++ b/src/pim/config.rs @@ -6,17 +6,40 @@ use super::kernel::Kernel; #[link_section = ".pim_config"] static mut PIM_CONFIG_REGION: [u8; 0x4000] = [0; 0x4000]; +const CACHE_LINE_SIZE: usize = 32; + pub struct PimWriter; impl PimWriter { pub fn write(&mut self, s: &str) { unsafe { + // Preload the cache lines so that no unnecessary fetch to memory is made + // This prevents unwanted PIM cycles when disabling PIM mode + // We cannot do this in a for loop as this triggers memory fetches itself + // Try to find a better solution + // asm!("dc zva, {val}", val = in(reg) &PIM_CONFIG_REGION[CACHE_LINE_SIZE*0]); + // asm!("dc zva, {val}", val = in(reg) &PIM_CONFIG_REGION[CACHE_LINE_SIZE*1]); + // asm!("dc zva, {val}", val = in(reg) &PIM_CONFIG_REGION[CACHE_LINE_SIZE*2]); + // asm!("dc zva, {val}", val = in(reg) &PIM_CONFIG_REGION[CACHE_LINE_SIZE*3]); + // asm!("dc zva, {val}", val = in(reg) &PIM_CONFIG_REGION[CACHE_LINE_SIZE*4]); + // asm!("dc zva, {val}", val = in(reg) &PIM_CONFIG_REGION[CACHE_LINE_SIZE*5]); + // asm!("dc zva, {val}", val = in(reg) &PIM_CONFIG_REGION[CACHE_LINE_SIZE*6]); + // asm!("dc zva, {val}", val = in(reg) &PIM_CONFIG_REGION[CACHE_LINE_SIZE*7]); + // asm!("dc zva, {val}", val = in(reg) &PIM_CONFIG_REGION[CACHE_LINE_SIZE*8]); + // asm!("dc zva, {val}", val = in(reg) &PIM_CONFIG_REGION[CACHE_LINE_SIZE*9]); + // asm!("dc zva, {val}", val = in(reg) &PIM_CONFIG_REGION[CACHE_LINE_SIZE*10]); + // asm!("dc zva, {val}", val = in(reg) &PIM_CONFIG_REGION[CACHE_LINE_SIZE*11]); + // asm!("dc zva, {val}", val = in(reg) &PIM_CONFIG_REGION[CACHE_LINE_SIZE*12]); + // asm!("dc zva, {val}", val = in(reg) &PIM_CONFIG_REGION[CACHE_LINE_SIZE*13]); + // asm!("dc zva, {val}", val = in(reg) &PIM_CONFIG_REGION[CACHE_LINE_SIZE*14]); + // asm!("dc zva, {val}", val = in(reg) &PIM_CONFIG_REGION[CACHE_LINE_SIZE*15]); + + // Do the copy PIM_CONFIG_REGION[..s.len()].copy_from_slice(s.as_bytes()); PIM_CONFIG_REGION[s.len()] = b'\0'; // Flush all cache lines that were affected by write operation - // A cache line is 32 bytes so we only need to flush every 64th virtual address - for element in PIM_CONFIG_REGION[..s.len()].iter().step_by(32) { + for element in PIM_CONFIG_REGION[..s.len()].iter().step_by(CACHE_LINE_SIZE) { asm!("dc civac, {val}", val = in(reg) element); } diff --git a/src/pim/instruction.rs b/src/pim/instruction.rs index 8eba06f..c53cf1e 100644 --- a/src/pim/instruction.rs +++ b/src/pim/instruction.rs @@ -1,16 +1,18 @@ use serde::Serialize; #[derive(Clone, Copy, Debug, Serialize)] +#[serde(tag = "type")] pub enum Instruction { NOP, - JUMP(JUMP), + EXIT, + JUMP { offset: i16, count: u16 }, + MOV { src: File, dst: File }, } #[derive(Clone, Copy, Debug, Serialize)] -pub struct NOP; - -#[derive(Clone, Copy, Debug, Serialize)] -pub struct JUMP { - pub offset: u8, - pub count: u8, +pub enum File { + GRF { index: u8 }, + SRF_M { index: u8 }, + SRF_A { index: u8 }, + BANK, } diff --git a/src/pim/kernel.rs b/src/pim/kernel.rs index f297dab..4c1a913 100644 --- a/src/pim/kernel.rs +++ b/src/pim/kernel.rs @@ -1,7 +1,41 @@ -use super::instruction::{Instruction, NOP}; +use super::instruction::Instruction; use serde::Serialize; #[derive(Debug, Serialize)] pub struct Kernel([Instruction; 32]); pub const NOP_KERNEL: Kernel = Kernel([Instruction::NOP; 32]); +pub const TEST_KERNEL: Kernel = Kernel([ + Instruction::NOP, + Instruction::EXIT, + Instruction::JUMP { offset: 1, count: 12 }, + Instruction::EXIT, + Instruction::NOP, + Instruction::EXIT, + Instruction::NOP, + Instruction::EXIT, + Instruction::NOP, + Instruction::EXIT, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, + Instruction::NOP, +]);