Add conveniance functions for a PIM array
This commit is contained in:
@@ -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]
|
||||
|
||||
@@ -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 = .;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod array;
|
||||
pub mod config;
|
||||
pub mod kernel;
|
||||
pub mod operation;
|
||||
|
||||
@@ -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()))
|
||||
}
|
||||
}
|
||||
|
||||
18
pim-os/src/pim/operation.rs
Normal file
18
pim-os/src/pim/operation.rs
Normal 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() {}
|
||||
Reference in New Issue
Block a user