Execute a simple NOP kernel
This commit is contained in:
66
src/main.rs
66
src/main.rs
@@ -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?}",
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
]);
|
||||||
|
|||||||
Reference in New Issue
Block a user