Execute a simple NOP kernel

This commit is contained in:
2023-11-26 07:17:44 +01:00
parent b6d043dbd8
commit 8f1c43defd
4 changed files with 104 additions and 41 deletions

View File

@@ -7,7 +7,11 @@ use core::{
panic::PanicInfo, panic::PanicInfo,
sync::atomic::{self, Ordering}, 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; use uart::Uart0;
mod m5ops; mod m5ops;
@@ -21,50 +25,50 @@ static mut TEST_ARRAY: PimArray = PimArray([0; 256]);
#[no_mangle] #[no_mangle]
pub extern "C" fn entry() -> ! { pub extern "C" fn entry() -> ! {
let mut pim_config = pim::config::PimConfig { let mut pim_config = pim::config::PimConfig {
bank_mode: pim::config::BankMode::AllBank, bank_mode: pim::config::BankMode::PimAllBank,
kernel: NOP_KERNEL, kernel: TEST_KERNEL,
}; };
let mut pim_writer = pim::config::PimWriter; let mut pim_writer = pim::config::PimWriter;
let mut uart = Uart0 {}; let mut uart = Uart0 {};
unsafe { unsafe {
// Toggle AllBank writeln!(
pim_writer.write( &mut uart,
serde_json_core::to_string::<PimConfig, 256>(&pim_config) "PIM array is at {:x?}",
.unwrap() core::ptr::addr_of!(TEST_ARRAY)
.as_str(), )
); .unwrap();
writeln!(&mut uart, "Read from all banks").unwrap();
writeln!(&mut uart, "Enable AllBank").unwrap(); // Invalidate array just in case
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
for element in TEST_ARRAY.0.iter().step_by(8) { 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( pim_writer.write(
serde_json_core::to_string::<PimConfig, 256>(&pim_config) serde_json_core::to_string::<PimConfig, 1024>(&pim_config)
.unwrap() .unwrap()
.as_str(), .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::<PimConfig, 1024>(&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!( writeln!(
&mut uart, &mut uart,
"{:?}: {:x?}", "{:?}: {:x?}",

View File

@@ -6,17 +6,40 @@ use super::kernel::Kernel;
#[link_section = ".pim_config"] #[link_section = ".pim_config"]
static mut PIM_CONFIG_REGION: [u8; 0x4000] = [0; 0x4000]; static mut PIM_CONFIG_REGION: [u8; 0x4000] = [0; 0x4000];
const CACHE_LINE_SIZE: usize = 32;
pub struct PimWriter; pub struct PimWriter;
impl PimWriter { impl PimWriter {
pub fn write(&mut self, s: &str) { pub fn write(&mut self, s: &str) {
unsafe { 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()].copy_from_slice(s.as_bytes());
PIM_CONFIG_REGION[s.len()] = b'\0'; PIM_CONFIG_REGION[s.len()] = b'\0';
// Flush all cache lines that were affected by write operation // 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(CACHE_LINE_SIZE) {
for element in PIM_CONFIG_REGION[..s.len()].iter().step_by(32) {
asm!("dc civac, {val}", val = in(reg) element); asm!("dc civac, {val}", val = in(reg) element);
} }

View File

@@ -1,16 +1,18 @@
use serde::Serialize; use serde::Serialize;
#[derive(Clone, Copy, Debug, Serialize)] #[derive(Clone, Copy, Debug, Serialize)]
#[serde(tag = "type")]
pub enum Instruction { pub enum Instruction {
NOP, NOP,
JUMP(JUMP), EXIT,
JUMP { offset: i16, count: u16 },
MOV { src: File, dst: File },
} }
#[derive(Clone, Copy, Debug, Serialize)] #[derive(Clone, Copy, Debug, Serialize)]
pub struct NOP; pub enum File {
GRF { index: u8 },
#[derive(Clone, Copy, Debug, Serialize)] SRF_M { index: u8 },
pub struct JUMP { SRF_A { index: u8 },
pub offset: u8, BANK,
pub count: u8,
} }

View File

@@ -1,7 +1,41 @@
use super::instruction::{Instruction, NOP}; use super::instruction::Instruction;
use serde::Serialize; use serde::Serialize;
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
pub struct Kernel([Instruction; 32]); pub struct Kernel([Instruction; 32]);
pub const NOP_KERNEL: Kernel = Kernel([Instruction::NOP; 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,
]);