Add conveniance functions for a PIM array

This commit is contained in:
2023-12-01 18:00:28 +01:00
parent 54bf6bda11
commit 2547f7030d
6 changed files with 160 additions and 63 deletions

View File

@@ -8,6 +8,7 @@ aarch64-cpu = "9.4.0"
half = { version = "2.3.1", default-features = false }
serde = { version = "1.0", default-features = false, features = ["derive"] }
serde-json-core = "0.5.1"
pim-isa = { path = "../pim-isa", default-features = false }
[profile.dev]

View File

@@ -1,6 +1,6 @@
MEMORY
{
bootmem : ORIGIN = 0x0, LENGTH = 0x10000
bootmem : ORIGIN = 0x0, LENGTH = 0x100000
dram : ORIGIN = 0x80000000, LENGTH = 0x100000000
}
@@ -16,6 +16,6 @@ SECTIONS
.bss : { *(.bss) } > dram
. = ALIGN(8);
. = . + 0x8000;
. = . + 0x100000; # 1 MiB Stack
LD_STACK_PTR = .;
}

View File

@@ -2,13 +2,12 @@
#![no_main]
use core::{
arch::{asm, global_asm},
arch::global_asm,
fmt::Write,
panic::PanicInfo,
sync::atomic::{self, Ordering},
};
use half::f16;
use pim::{array::BankArray, kernel::TEST_KERNEL};
use pim::{array::ComputeArray, kernel::TEST_KERNEL};
use pim_isa::{BankMode, PimConfig};
use uart::Uart0;
@@ -18,8 +17,6 @@ mod uart;
global_asm!(include_str!("start.s"));
static mut TEST_ARRAY: BankArray = BankArray([f16::ZERO; 512]);
#[no_mangle]
pub extern "C" fn entry() -> ! {
let mut pim_config = PimConfig {
@@ -28,67 +25,50 @@ pub extern "C" fn entry() -> ! {
};
let mut pim_writer = pim::config::PimWriter;
let mut test_array: ComputeArray<2> = ComputeArray::default();
let mut uart = Uart0 {};
unsafe {
writeln!(
&mut uart,
"PIM array is at {:x?}",
core::ptr::addr_of!(TEST_ARRAY)
)
.unwrap();
writeln!(&mut uart, "Read from all banks").unwrap();
// Invalidate and flush array just in case
for element in TEST_ARRAY.0.iter().step_by(8) {
asm!("dc civac, {val}", val = in(reg) element);
}
asm!("dsb sy");
writeln!(
&mut uart,
"PIM array is at {:x?}",
core::ptr::addr_of!(test_array)
)
.unwrap();
writeln!(&mut uart, "Read from all banks").unwrap();
// Invalidate and flush array just in case
test_array.invalidate_flush();
// Fetch single cache line in array
// core::ptr::read_volatile(&TEST_ARRAY.0[0]);
// Zero array to prevent fetch
let bank_array = &mut test_array.0[0];
bank_array.preload_zero();
// Zero array to prevent fetch
// for element in TEST_ARRAY.0.iter().step_by(8) {
// asm!("dc zva, {val}", val = in(reg) element);
// }
asm!("dc zva, {val}", val = in(reg) &TEST_ARRAY.0[0]);
asm!("dsb sy");
pim_writer.write(
serde_json_core::to_string::<PimConfig, 1024>(&pim_config)
.unwrap()
.as_str(),
);
pim_writer.write(
serde_json_core::to_string::<PimConfig, 1024>(&pim_config)
.unwrap()
.as_str(),
);
bank_array.write_data();
core::ptr::write_volatile(&mut TEST_ARRAY.0[0], f16::ZERO);
pim_config.bank_mode = BankMode::SingleBank;
pim_writer.write(
serde_json_core::to_string::<PimConfig, 1024>(&pim_config)
.unwrap()
.as_str(),
);
// Invalidate and flush
// for element in TEST_ARRAY.0.iter().step_by(8) {
asm!("dc civac, {val}", val = in(reg) &TEST_ARRAY.0[0]);
// }
asm!("dsb sy");
// Invalidate and flush
test_array.invalidate();
pim_config.bank_mode = 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!(
&mut uart,
"{:?}: {:x?}",
core::ptr::addr_of!(TEST_ARRAY),
TEST_ARRAY
)
.unwrap();
}
writeln!(
&mut uart,
"{:?}: {:x?}",
core::ptr::addr_of!(test_array),
test_array
)
.unwrap();
m5ops::exit();

View File

@@ -1,3 +1,4 @@
pub mod array;
pub mod config;
pub mod kernel;
pub mod operation;

View File

@@ -1,8 +1,105 @@
use core::arch::asm;
use half::f16;
#[derive(Debug)]
#[repr(C, align(1024))]
pub struct BankArray(pub [f16; 512]);
const NUMBER_OF_BANKS: usize = 32;
const ELEMENTS_PER_CACHE_LINE: usize = 16;
const ELEMENTS_PER_BANK_ARRAY: usize = NUMBER_OF_BANKS * ELEMENTS_PER_CACHE_LINE;
#[derive(Debug)]
#[derive(Clone, Debug)]
#[repr(C, align(1024))]
pub struct BankArray(pub [f16; ELEMENTS_PER_BANK_ARRAY]);
impl Default for BankArray {
fn default() -> Self {
Self([f16::ZERO; ELEMENTS_PER_BANK_ARRAY])
}
}
impl BankArray {
pub fn write_data(&mut self) {
unsafe {
// Write to first bank
let first_bank = &mut self.0[0];
core::ptr::write_volatile(first_bank, f16::ZERO);
self.invalidate_flush_single_bank(0);
}
}
pub fn read_data(&self) {
unsafe {
// Read from first bank
let first_bank = &self.0[0];
core::ptr::read_volatile(first_bank);
self.invalidate_flush_single_bank(0);
}
}
pub fn invalidate(&self) {
(0..ELEMENTS_PER_BANK_ARRAY)
.step_by(ELEMENTS_PER_CACHE_LINE)
.for_each(|idx| self.invalidate_single_bank(idx));
}
pub fn invalidate_single_bank(&self, idx: usize) {
unsafe {
// Invalidate and flush first bank
asm!("dc ivac, {val}", val = in(reg) &self.0[idx]);
asm!("dsb sy");
}
}
pub fn invalidate_flush(&self) {
(0..ELEMENTS_PER_BANK_ARRAY)
.step_by(ELEMENTS_PER_CACHE_LINE)
.for_each(|idx| self.invalidate_flush_single_bank(idx));
}
pub fn invalidate_flush_single_bank(&self, idx: usize) {
unsafe {
// Invalidate and flush first bank
asm!("dc civac, {val}", val = in(reg) &self.0[idx]);
asm!("dsb sy");
}
}
pub fn preload_zero(&self) {
(0..ELEMENTS_PER_BANK_ARRAY)
.step_by(ELEMENTS_PER_CACHE_LINE)
.for_each(|idx| self.preload_zero_single_bank(idx));
}
pub fn preload_zero_single_bank(&self, idx: usize) {
unsafe {
// Preload first bank
asm!("dc zva, {val}", val = in(reg) &self.0[idx]);
asm!("dsb sy");
}
}
}
#[derive(Clone, Debug)]
pub struct ComputeArray<const N: usize>(pub [BankArray; N]);
impl<const N: usize> ComputeArray<N> {
pub fn invalidate_flush(&self) {
self.0
.iter()
.for_each(|bank_array| bank_array.invalidate_flush());
}
pub fn invalidate(&self) {
self.0.iter().for_each(|bank_array| bank_array.invalidate());
}
pub fn preload_zero(&self) {
self.0
.iter()
.for_each(|bank_array| bank_array.preload_zero());
}
}
impl<const N: usize> Default for ComputeArray<N> {
fn default() -> Self {
Self(core::array::from_fn(|_| Default::default()))
}
}

View File

@@ -0,0 +1,18 @@
use super::array::BankArray;
use core::arch::asm;
fn execute_bank_write(bank_array: &BankArray) {
unsafe {
// Invalidate and flush cache line
asm!("dc civac, {val}", val = in(reg) bank_array);
asm!("dsb sy");
// Zero cache line
asm!("dc zva, {val}", val = in(reg) bank_array);
asm!("dsb sy");
}
}
fn execute_bank_read() {}
fn execute_generic_inst() {}