First steps towards matrix multiplication
This commit is contained in:
@@ -64,8 +64,8 @@ impl Kernel {
|
|||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct PimConfig {
|
pub struct PimConfig {
|
||||||
pub bank_mode: BankMode,
|
pub bank_mode: Option<BankMode>,
|
||||||
pub kernel: Kernel,
|
pub kernel: Option<Kernel>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
|
|||||||
8
pim-os/Cargo.lock
generated
8
pim-os/Cargo.lock
generated
@@ -182,9 +182,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.71"
|
version = "1.0.72"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8"
|
checksum = "a293318316cf6478ec1ad2a21c49390a8d5b5eae9fab736467d93fbc0edc29c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@@ -285,9 +285,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.42"
|
version = "2.0.43"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b7d0a2c048d661a1a59fcd7355baa232f7ed34e0ee4df2eef3c1c1c0d3852d8"
|
checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ use core::{
|
|||||||
use half::f16;
|
use half::f16;
|
||||||
use nalgebra::Matrix;
|
use nalgebra::Matrix;
|
||||||
use pim::{
|
use pim::{
|
||||||
array::{PimMatrixArena, PimRegion, PimStorage},
|
array::{DummyArray, PimMatrixArena, PimRegion, PimStorage, NUMBER_OF_BANKS},
|
||||||
kernel::TEST_KERNEL,
|
kernel::{execute_matrix_add, execute_matrix_multiply, MATRIX_ADD, MATRIX_MUL},
|
||||||
state::PimState,
|
state::PimState,
|
||||||
vector::{F16x1, F16x16},
|
vector::{F16x1, F16x16},
|
||||||
};
|
};
|
||||||
@@ -28,55 +28,64 @@ mod uart;
|
|||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn entry() -> ! {
|
pub extern "C" fn entry() -> ! {
|
||||||
let mut uart = Uart0;
|
let mut uart = Uart0;
|
||||||
let mut pim_state = PimState::new(&TEST_KERNEL);
|
let mut pim_state = PimState::new(&MATRIX_MUL);
|
||||||
|
pim_state.set_kernel();
|
||||||
|
|
||||||
let pim_matrix_arena0 = RefCell::new(PimMatrixArena([[F16x16::default(); 8]; 8]));
|
let pim_matrix_arena0 = RefCell::new(PimMatrixArena(
|
||||||
let pim_matrix_arena1 = RefCell::new(PimMatrixArena([[F16x16::default(); 8]; 8]));
|
[[[F16x16::default(); NUMBER_OF_BANKS]; 8]; 8],
|
||||||
|
));
|
||||||
|
let pim_matrix_arena1 = RefCell::new(PimMatrixArena(
|
||||||
|
[[[F16x16::default(); NUMBER_OF_BANKS]; 8]; 8],
|
||||||
|
));
|
||||||
|
let pim_matrix_arena2 = RefCell::new(PimMatrixArena(
|
||||||
|
[[[F16x16::default(); NUMBER_OF_BANKS]; 8]; 8],
|
||||||
|
));
|
||||||
let pim_storage0 = PimStorage {
|
let pim_storage0 = PimStorage {
|
||||||
arena: &pim_matrix_arena0,
|
arena: &pim_matrix_arena0,
|
||||||
index: 0,
|
index: 0,
|
||||||
|
row_major: true,
|
||||||
};
|
};
|
||||||
let pim_storage1 = PimStorage {
|
let pim_storage1 = PimStorage {
|
||||||
arena: &pim_matrix_arena1,
|
arena: &pim_matrix_arena1,
|
||||||
index: 0,
|
index: 0,
|
||||||
|
row_major: false,
|
||||||
|
};
|
||||||
|
let pim_storage2 = PimStorage {
|
||||||
|
arena: &pim_matrix_arena2,
|
||||||
|
index: 0,
|
||||||
|
row_major: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut matrix0 = Matrix::from_data(pim_storage0);
|
let mut matrix0 = Matrix::from_data(pim_storage0);
|
||||||
matrix0.fill_column(0, F16x1(f16::ZERO));
|
matrix0.fill(F16x1(f16::ONE));
|
||||||
matrix0.fill_column(1, F16x1(f16::ONE));
|
|
||||||
matrix0.fill_column(2, F16x1(f16::PI));
|
|
||||||
matrix0.fill_column(3, F16x1(f16::E));
|
|
||||||
matrix0.fill_column(4, F16x1(f16::EPSILON));
|
|
||||||
matrix0.fill_column(5, F16x1(f16::SQRT_2));
|
|
||||||
matrix0.fill_column(6, F16x1(f16::LN_2));
|
|
||||||
matrix0.fill_column(7, F16x1(f16::LN_10));
|
|
||||||
|
|
||||||
let mut matrix1 = Matrix::from_data(pim_storage1);
|
let mut matrix1 = Matrix::from_data(pim_storage1);
|
||||||
matrix1.fill_lower_triangle(F16x1(f16::ONE), 0);
|
matrix1.fill_lower_triangle(F16x1(f16::ONE), 0);
|
||||||
|
|
||||||
writeln!(&mut uart, "{matrix0} + {matrix1}\n=").unwrap();
|
let matrix2 = Matrix::from_data(pim_storage2);
|
||||||
|
|
||||||
|
writeln!(&mut uart, "{matrix0} * {matrix1}\n=").unwrap();
|
||||||
|
|
||||||
// Invalidate and flush array just in case
|
// Invalidate and flush array just in case
|
||||||
pim_matrix_arena0.borrow_mut().invalidate_flush();
|
pim_matrix_arena0.borrow_mut().invalidate_flush();
|
||||||
pim_matrix_arena1.borrow_mut().invalidate_flush();
|
pim_matrix_arena1.borrow_mut().invalidate_flush();
|
||||||
|
pim_matrix_arena2.borrow_mut().invalidate_flush();
|
||||||
|
let dummy_array = DummyArray([F16x16::default(); NUMBER_OF_BANKS]);
|
||||||
barrier::dsb(barrier::SY);
|
barrier::dsb(barrier::SY);
|
||||||
|
|
||||||
pim_state.set_bank_mode(BankMode::PimAllBank);
|
// execute_matrix_add(&pim_matrix_arena0, &pim_matrix_arena1, &dummy_array);
|
||||||
pim_matrix_arena0
|
execute_matrix_multiply(
|
||||||
.borrow()
|
&mut pim_state,
|
||||||
.execute_instruction_read_dual_bank();
|
&pim_matrix_arena0,
|
||||||
pim_matrix_arena1
|
&pim_matrix_arena1,
|
||||||
.borrow()
|
&pim_matrix_arena2,
|
||||||
.execute_instruction_read_dual_bank();
|
&dummy_array,
|
||||||
pim_matrix_arena0
|
);
|
||||||
.borrow_mut()
|
|
||||||
.execute_instruction_write_dual_bank();
|
|
||||||
pim_state.set_bank_mode(BankMode::SingleBank);
|
|
||||||
|
|
||||||
pim_matrix_arena0.borrow_mut().invalidate();
|
pim_matrix_arena2.borrow_mut().invalidate();
|
||||||
barrier::dsb(barrier::SY);
|
barrier::dsb(barrier::SY);
|
||||||
|
|
||||||
writeln!(&mut uart, "{matrix0}").unwrap();
|
writeln!(&mut uart, "{matrix2}").unwrap();
|
||||||
|
|
||||||
m5ops::exit();
|
m5ops::exit();
|
||||||
|
|
||||||
|
|||||||
@@ -4,17 +4,16 @@ use core::{arch::asm, cell::RefCell};
|
|||||||
use half::f16;
|
use half::f16;
|
||||||
use nalgebra::{Const, Dyn, RawStorage, RawStorageMut};
|
use nalgebra::{Const, Dyn, RawStorage, RawStorageMut};
|
||||||
|
|
||||||
const NUMBER_OF_BANKS: usize = 32;
|
pub const NUMBER_OF_BANKS: usize = 32;
|
||||||
const EVEN_BANK_INDEX: usize = 0;
|
const EVEN_BANK_INDEX: usize = 0;
|
||||||
const ODD_BANK_INDEX: usize = 8;
|
const ODD_BANK_INDEX: usize = 8;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
#[repr(C, align(1024))]
|
#[repr(C, align(1024))]
|
||||||
pub struct PimMatrixArena<const R: usize, const C: usize>(pub [[F16x16; R]; C]);
|
pub struct PimMatrixArena<const R: usize, const C: usize>(pub [[[F16x16; NUMBER_OF_BANKS]; R]; C]);
|
||||||
|
|
||||||
impl<const R: usize, const C: usize> PimRegion for PimMatrixArena<R, C> {
|
impl<const R: usize, const C: usize> PimRegion for PimMatrixArena<R, C> {
|
||||||
const OCCUPIED_CACHE_LINES: usize = R * C;
|
const OCCUPIED_CACHE_LINES: usize = R * C * NUMBER_OF_BANKS;
|
||||||
const OCCUPIED_ROWS: usize = Self::OCCUPIED_CACHE_LINES / NUMBER_OF_BANKS;
|
|
||||||
|
|
||||||
fn bank_ptr(&self, bank_index: usize) -> *const f16 {
|
fn bank_ptr(&self, bank_index: usize) -> *const f16 {
|
||||||
unsafe { (self.0.as_ptr() as *const F16x16).add(bank_index) as *const f16 }
|
unsafe { (self.0.as_ptr() as *const F16x16).add(bank_index) as *const f16 }
|
||||||
@@ -29,6 +28,7 @@ impl<const R: usize, const C: usize> PimRegion for PimMatrixArena<R, C> {
|
|||||||
pub struct PimStorage<'a, const R: usize, const C: usize> {
|
pub struct PimStorage<'a, const R: usize, const C: usize> {
|
||||||
pub arena: &'a RefCell<PimMatrixArena<R, C>>,
|
pub arena: &'a RefCell<PimMatrixArena<R, C>>,
|
||||||
pub index: usize,
|
pub index: usize,
|
||||||
|
pub row_major: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<'a, const R: usize, const C: usize> RawStorage<F16x1, Const<R>, Const<C>>
|
unsafe impl<'a, const R: usize, const C: usize> RawStorage<F16x1, Const<R>, Const<C>>
|
||||||
@@ -46,7 +46,11 @@ unsafe impl<'a, const R: usize, const C: usize> RawStorage<F16x1, Const<R>, Cons
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn strides(&self) -> (Self::RStride, Self::CStride) {
|
fn strides(&self) -> (Self::RStride, Self::CStride) {
|
||||||
(Dyn(16), Dyn(16 * R))
|
if self.row_major {
|
||||||
|
(Dyn(16 * R * NUMBER_OF_BANKS), Dyn(16 * NUMBER_OF_BANKS))
|
||||||
|
} else {
|
||||||
|
(Dyn(16 * NUMBER_OF_BANKS), Dyn(16 * R * NUMBER_OF_BANKS))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_contiguous(&self) -> bool {
|
fn is_contiguous(&self) -> bool {
|
||||||
@@ -74,40 +78,36 @@ unsafe impl<'a, const R: usize, const C: usize> RawStorageMut<F16x1, Const<R>, C
|
|||||||
|
|
||||||
pub trait PimRegion {
|
pub trait PimRegion {
|
||||||
const OCCUPIED_CACHE_LINES: usize;
|
const OCCUPIED_CACHE_LINES: usize;
|
||||||
const OCCUPIED_ROWS: usize;
|
|
||||||
|
|
||||||
fn bank_ptr(&self, bank_index: usize) -> *const f16;
|
fn bank_ptr(&self, bank_index: usize) -> *const f16;
|
||||||
fn bank_ptr_mut(&mut self, bank_index: usize) -> *mut f16;
|
fn bank_ptr_mut(&mut self, bank_index: usize) -> *mut f16;
|
||||||
|
|
||||||
fn execute_instruction_read_single_bank(&self) {
|
fn execute_instruction_read_single_bank(&self, i: usize) {
|
||||||
for i in 0..Self::OCCUPIED_ROWS {
|
if !cfg!(feature = "cacheless") {
|
||||||
if !cfg!(feature = "cacheless") {
|
self.invalidate_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
||||||
self.invalidate_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
|
||||||
barrier::dsb(barrier::SY);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read from first bank
|
|
||||||
self.read_data_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
|
||||||
|
|
||||||
barrier::dsb(barrier::SY);
|
barrier::dsb(barrier::SY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read from first bank
|
||||||
|
self.read_data_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
||||||
|
|
||||||
|
barrier::dsb(barrier::SY);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_instruction_read_dual_bank(&self) {
|
fn execute_instruction_read_dual_bank(&self) {
|
||||||
for i in 0..Self::OCCUPIED_ROWS {
|
let i = 0;
|
||||||
if !cfg!(feature = "cacheless") {
|
if !cfg!(feature = "cacheless") {
|
||||||
self.invalidate_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
self.invalidate_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
||||||
self.invalidate_bank(ODD_BANK_INDEX + i * NUMBER_OF_BANKS);
|
self.invalidate_bank(ODD_BANK_INDEX + i * NUMBER_OF_BANKS);
|
||||||
|
|
||||||
barrier::dsb(barrier::SY);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read from first and second bank
|
|
||||||
self.read_data_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
|
||||||
self.read_data_bank(ODD_BANK_INDEX + i * NUMBER_OF_BANKS);
|
|
||||||
|
|
||||||
barrier::dsb(barrier::SY);
|
barrier::dsb(barrier::SY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read from first and second bank
|
||||||
|
self.read_data_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
||||||
|
self.read_data_bank(ODD_BANK_INDEX + i * NUMBER_OF_BANKS);
|
||||||
|
|
||||||
|
barrier::dsb(barrier::SY);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_data_bank(&self, bank_index: usize) {
|
fn read_data_bank(&self, bank_index: usize) {
|
||||||
@@ -117,43 +117,40 @@ pub trait PimRegion {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_instruction_write_single_bank(&mut self) {
|
fn execute_instruction_write_single_bank(&mut self, i: usize) {
|
||||||
for i in 0..Self::OCCUPIED_ROWS {
|
if !cfg!(feature = "cacheless") {
|
||||||
if !cfg!(feature = "cacheless") {
|
self.preload_zero_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
||||||
self.preload_zero_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
|
||||||
barrier::dsb(barrier::SY);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write to first bank
|
|
||||||
self.write_data_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
|
||||||
|
|
||||||
if !cfg!(feature = "cacheless") {
|
|
||||||
self.invalidate_flush_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
|
||||||
}
|
|
||||||
|
|
||||||
barrier::dsb(barrier::SY);
|
barrier::dsb(barrier::SY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write to first bank
|
||||||
|
self.write_data_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
||||||
|
|
||||||
|
if !cfg!(feature = "cacheless") {
|
||||||
|
self.invalidate_flush_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
||||||
|
}
|
||||||
|
|
||||||
|
barrier::dsb(barrier::SY);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_instruction_write_dual_bank(&mut self) {
|
fn execute_instruction_write_dual_bank(&mut self) {
|
||||||
for i in 0..Self::OCCUPIED_ROWS {
|
let i = 0;
|
||||||
if !cfg!(feature = "cacheless") {
|
if !cfg!(feature = "cacheless") {
|
||||||
self.preload_zero_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
self.preload_zero_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
||||||
self.preload_zero_bank(ODD_BANK_INDEX + i * NUMBER_OF_BANKS);
|
self.preload_zero_bank(ODD_BANK_INDEX + i * NUMBER_OF_BANKS);
|
||||||
barrier::dsb(barrier::SY);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write to first and second bank
|
|
||||||
self.write_data_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
|
||||||
self.write_data_bank(ODD_BANK_INDEX + i * NUMBER_OF_BANKS);
|
|
||||||
|
|
||||||
if !cfg!(feature = "cacheless") {
|
|
||||||
self.invalidate_flush_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
|
||||||
self.invalidate_flush_bank(ODD_BANK_INDEX + i * NUMBER_OF_BANKS);
|
|
||||||
}
|
|
||||||
|
|
||||||
barrier::dsb(barrier::SY);
|
barrier::dsb(barrier::SY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write to first and second bank
|
||||||
|
self.write_data_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
||||||
|
self.write_data_bank(ODD_BANK_INDEX + i * NUMBER_OF_BANKS);
|
||||||
|
|
||||||
|
if !cfg!(feature = "cacheless") {
|
||||||
|
self.invalidate_flush_bank(EVEN_BANK_INDEX + i * NUMBER_OF_BANKS);
|
||||||
|
self.invalidate_flush_bank(ODD_BANK_INDEX + i * NUMBER_OF_BANKS);
|
||||||
|
}
|
||||||
|
|
||||||
|
barrier::dsb(barrier::SY);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_data_bank(&mut self, bank_index: usize) {
|
fn write_data_bank(&mut self, bank_index: usize) {
|
||||||
@@ -203,7 +200,6 @@ pub struct DummyArray(pub [F16x16; NUMBER_OF_BANKS]);
|
|||||||
|
|
||||||
impl PimRegion for DummyArray {
|
impl PimRegion for DummyArray {
|
||||||
const OCCUPIED_CACHE_LINES: usize = NUMBER_OF_BANKS;
|
const OCCUPIED_CACHE_LINES: usize = NUMBER_OF_BANKS;
|
||||||
const OCCUPIED_ROWS: usize = 1;
|
|
||||||
|
|
||||||
fn bank_ptr(&self, bank_index: usize) -> *const f16 {
|
fn bank_ptr(&self, bank_index: usize) -> *const f16 {
|
||||||
&self.0[bank_index] as *const F16x16 as *const f16
|
&self.0[bank_index] as *const F16x16 as *const f16
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
use pim_isa::{File, Instruction, Kernel};
|
use core::cell::RefCell;
|
||||||
|
|
||||||
pub const TEST_KERNEL: Kernel = Kernel([
|
use pim_isa::{BankMode, File, Instruction, Kernel};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
array::{DummyArray, PimMatrixArena, PimRegion},
|
||||||
|
state::PimState,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const MATRIX_ADD: Kernel = Kernel([
|
||||||
Instruction::MOV {
|
Instruction::MOV {
|
||||||
src: File::Bank,
|
src: File::Bank,
|
||||||
dst: File::GrfA { index: 0 },
|
dst: File::GrfA { index: 0 },
|
||||||
@@ -41,28 +48,6 @@ pub const TEST_KERNEL: Kernel = Kernel([
|
|||||||
dst: File::GrfB { index: 1 },
|
dst: File::GrfB { index: 1 },
|
||||||
aam: false,
|
aam: false,
|
||||||
},
|
},
|
||||||
// Instruction::MOV {
|
|
||||||
// src: File::Bank,
|
|
||||||
// dst: File::GrfA { index: 1 },
|
|
||||||
// },
|
|
||||||
// Instruction::MOV {
|
|
||||||
// src: File::Bank,
|
|
||||||
// dst: File::GrfB { index: 1 },
|
|
||||||
// },
|
|
||||||
// Instruction::MAC {
|
|
||||||
// src0: File::Bank,
|
|
||||||
// src1: File::GrfA { index: 0 },
|
|
||||||
// src2: File::GrfB { index: 0 },
|
|
||||||
// dst: File::GrfB { index: 0 },
|
|
||||||
// aam: false,
|
|
||||||
// },
|
|
||||||
// Instruction::MAC {
|
|
||||||
// src0: File::Bank,
|
|
||||||
// src1: File::GrfA { index: 1 },
|
|
||||||
// src2: File::GrfB { index: 1 },
|
|
||||||
// dst: File::GrfB { index: 1 },
|
|
||||||
// aam: false,
|
|
||||||
// },
|
|
||||||
Instruction::FILL {
|
Instruction::FILL {
|
||||||
src: File::GrfA { index: 0 },
|
src: File::GrfA { index: 0 },
|
||||||
dst: File::Bank,
|
dst: File::Bank,
|
||||||
@@ -101,59 +86,239 @@ pub const TEST_KERNEL: Kernel = Kernel([
|
|||||||
Instruction::NOP,
|
Instruction::NOP,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// pub const TEST_KERNEL: Kernel = Kernel([
|
pub fn execute_matrix_add(
|
||||||
// Instruction::MOV {
|
pim_matrix_arena0: &RefCell<PimMatrixArena<8, 8>>,
|
||||||
// src: File::Bank,
|
pim_matrix_arena1: &RefCell<PimMatrixArena<8, 8>>,
|
||||||
// dst: File::GrfA { index: 0 },
|
dummy_array: &DummyArray,
|
||||||
// },
|
) {
|
||||||
// Instruction::MOV {
|
// pim_matrix_arena0
|
||||||
// src: File::Bank,
|
// .borrow()
|
||||||
// dst: File::GrfA { index: 1 },
|
// .execute_instruction_read_dual_bank();
|
||||||
// },
|
// pim_matrix_arena1
|
||||||
// Instruction::ADD {
|
// .borrow()
|
||||||
// src0: File::Bank,
|
// .execute_instruction_read_dual_bank();
|
||||||
// src1: File::GrfA { index: 0 },
|
// pim_matrix_arena0
|
||||||
// dst: File::GrfA { index: 0 },
|
// .borrow_mut()
|
||||||
// aam: false,
|
// .execute_instruction_write_dual_bank();
|
||||||
// },
|
// dummy_array.execute_instruction_read_single_bank();
|
||||||
// Instruction::ADD {
|
}
|
||||||
// src0: File::Bank,
|
|
||||||
// src1: File::GrfA { index: 1 },
|
pub const MATRIX_MUL: Kernel = Kernel([
|
||||||
// dst: File::GrfA { index: 1 },
|
Instruction::MOV {
|
||||||
// aam: false,
|
src: File::Bank,
|
||||||
// },
|
dst: File::GrfA { index: 0 },
|
||||||
// Instruction::FILL {
|
},
|
||||||
// src: File::GrfA { index: 0 },
|
Instruction::MOV {
|
||||||
// dst: File::Bank,
|
src: File::Bank,
|
||||||
// },
|
dst: File::GrfA { index: 1 },
|
||||||
// Instruction::FILL {
|
},
|
||||||
// src: File::GrfA { index: 1 },
|
Instruction::MOV {
|
||||||
// dst: File::Bank,
|
src: File::Bank,
|
||||||
// },
|
dst: File::GrfA { index: 2 },
|
||||||
// Instruction::EXIT,
|
},
|
||||||
// Instruction::NOP,
|
Instruction::MOV {
|
||||||
// Instruction::NOP,
|
src: File::Bank,
|
||||||
// Instruction::NOP,
|
dst: File::GrfA { index: 3 },
|
||||||
// Instruction::NOP,
|
},
|
||||||
// Instruction::NOP,
|
Instruction::MOV {
|
||||||
// Instruction::NOP,
|
src: File::Bank,
|
||||||
// Instruction::NOP,
|
dst: File::GrfA { index: 4 },
|
||||||
// Instruction::NOP,
|
},
|
||||||
// Instruction::NOP,
|
Instruction::MOV {
|
||||||
// Instruction::NOP,
|
src: File::Bank,
|
||||||
// Instruction::NOP,
|
dst: File::GrfA { index: 5 },
|
||||||
// Instruction::NOP,
|
},
|
||||||
// Instruction::NOP,
|
Instruction::MOV {
|
||||||
// Instruction::NOP,
|
src: File::Bank,
|
||||||
// Instruction::NOP,
|
dst: File::GrfA { index: 6 },
|
||||||
// Instruction::NOP,
|
},
|
||||||
// Instruction::NOP,
|
Instruction::MOV {
|
||||||
// Instruction::NOP,
|
src: File::Bank,
|
||||||
// Instruction::NOP,
|
dst: File::GrfA { index: 7 },
|
||||||
// Instruction::NOP,
|
},
|
||||||
// Instruction::NOP,
|
Instruction::MAC {
|
||||||
// Instruction::NOP,
|
src0: File::Bank,
|
||||||
// Instruction::NOP,
|
src1: File::GrfA { index: 0 },
|
||||||
// Instruction::NOP,
|
src2: File::GrfB { index: 0 },
|
||||||
// Instruction::NOP,
|
dst: File::GrfB { index: 0 },
|
||||||
// ]);
|
aam: false,
|
||||||
|
},
|
||||||
|
Instruction::MAC {
|
||||||
|
src0: File::Bank,
|
||||||
|
src1: File::GrfA { index: 1 },
|
||||||
|
src2: File::GrfB { index: 0 },
|
||||||
|
dst: File::GrfB { index: 0 },
|
||||||
|
aam: false,
|
||||||
|
},
|
||||||
|
Instruction::MAC {
|
||||||
|
src0: File::Bank,
|
||||||
|
src1: File::GrfA { index: 2 },
|
||||||
|
src2: File::GrfB { index: 0 },
|
||||||
|
dst: File::GrfB { index: 0 },
|
||||||
|
aam: false,
|
||||||
|
},
|
||||||
|
Instruction::MAC {
|
||||||
|
src0: File::Bank,
|
||||||
|
src1: File::GrfA { index: 3 },
|
||||||
|
src2: File::GrfB { index: 0 },
|
||||||
|
dst: File::GrfB { index: 0 },
|
||||||
|
aam: false,
|
||||||
|
},
|
||||||
|
Instruction::MAC {
|
||||||
|
src0: File::Bank,
|
||||||
|
src1: File::GrfA { index: 4 },
|
||||||
|
src2: File::GrfB { index: 0 },
|
||||||
|
dst: File::GrfB { index: 0 },
|
||||||
|
aam: false,
|
||||||
|
},
|
||||||
|
Instruction::MAC {
|
||||||
|
src0: File::Bank,
|
||||||
|
src1: File::GrfA { index: 5 },
|
||||||
|
src2: File::GrfB { index: 0 },
|
||||||
|
dst: File::GrfB { index: 0 },
|
||||||
|
aam: false,
|
||||||
|
},
|
||||||
|
Instruction::MAC {
|
||||||
|
src0: File::Bank,
|
||||||
|
src1: File::GrfA { index: 6 },
|
||||||
|
src2: File::GrfB { index: 0 },
|
||||||
|
dst: File::GrfB { index: 0 },
|
||||||
|
aam: false,
|
||||||
|
},
|
||||||
|
Instruction::MAC {
|
||||||
|
src0: File::Bank,
|
||||||
|
src1: File::GrfA { index: 7 },
|
||||||
|
src2: File::GrfB { index: 0 },
|
||||||
|
dst: File::GrfB { index: 0 },
|
||||||
|
aam: false,
|
||||||
|
},
|
||||||
|
Instruction::FILL {
|
||||||
|
src: File::GrfB { index: 0 },
|
||||||
|
dst: File::Bank,
|
||||||
|
},
|
||||||
|
Instruction::FILL {
|
||||||
|
src: File::GrfB { index: 1 },
|
||||||
|
dst: File::Bank,
|
||||||
|
},
|
||||||
|
Instruction::FILL {
|
||||||
|
src: File::GrfB { index: 2 },
|
||||||
|
dst: File::Bank,
|
||||||
|
},
|
||||||
|
Instruction::FILL {
|
||||||
|
src: File::GrfB { index: 3 },
|
||||||
|
dst: File::Bank,
|
||||||
|
},
|
||||||
|
Instruction::FILL {
|
||||||
|
src: File::GrfB { index: 4 },
|
||||||
|
dst: File::Bank,
|
||||||
|
},
|
||||||
|
Instruction::FILL {
|
||||||
|
src: File::GrfB { index: 5 },
|
||||||
|
dst: File::Bank,
|
||||||
|
},
|
||||||
|
Instruction::FILL {
|
||||||
|
src: File::GrfB { index: 6 },
|
||||||
|
dst: File::Bank,
|
||||||
|
},
|
||||||
|
Instruction::FILL {
|
||||||
|
src: File::GrfB { index: 7 },
|
||||||
|
dst: File::Bank,
|
||||||
|
},
|
||||||
|
Instruction::EXIT,
|
||||||
|
Instruction::NOP,
|
||||||
|
Instruction::NOP,
|
||||||
|
Instruction::NOP,
|
||||||
|
Instruction::NOP,
|
||||||
|
Instruction::NOP,
|
||||||
|
Instruction::NOP,
|
||||||
|
Instruction::NOP,
|
||||||
|
]);
|
||||||
|
|
||||||
|
pub fn execute_matrix_multiply<const R: usize, const C: usize>(
|
||||||
|
pim_state: &mut PimState,
|
||||||
|
pim_matrix_arena0: &RefCell<PimMatrixArena<R, C>>,
|
||||||
|
pim_matrix_arena1: &RefCell<PimMatrixArena<R, C>>,
|
||||||
|
pim_matrix_arena2: &RefCell<PimMatrixArena<R, C>>,
|
||||||
|
dummy_array: &DummyArray,
|
||||||
|
) {
|
||||||
|
pim_state.set_bank_mode(BankMode::PimAllBank);
|
||||||
|
|
||||||
|
pim_matrix_arena0
|
||||||
|
.borrow()
|
||||||
|
.execute_instruction_read_single_bank(0);
|
||||||
|
pim_matrix_arena0
|
||||||
|
.borrow()
|
||||||
|
.execute_instruction_read_single_bank(1);
|
||||||
|
pim_matrix_arena0
|
||||||
|
.borrow()
|
||||||
|
.execute_instruction_read_single_bank(2);
|
||||||
|
pim_matrix_arena0
|
||||||
|
.borrow()
|
||||||
|
.execute_instruction_read_single_bank(3);
|
||||||
|
pim_matrix_arena0
|
||||||
|
.borrow()
|
||||||
|
.execute_instruction_read_single_bank(4);
|
||||||
|
pim_matrix_arena0
|
||||||
|
.borrow()
|
||||||
|
.execute_instruction_read_single_bank(5);
|
||||||
|
pim_matrix_arena0
|
||||||
|
.borrow()
|
||||||
|
.execute_instruction_read_single_bank(6);
|
||||||
|
pim_matrix_arena0
|
||||||
|
.borrow()
|
||||||
|
.execute_instruction_read_single_bank(7);
|
||||||
|
|
||||||
|
pim_matrix_arena1
|
||||||
|
.borrow()
|
||||||
|
.execute_instruction_read_single_bank(0);
|
||||||
|
pim_matrix_arena1
|
||||||
|
.borrow()
|
||||||
|
.execute_instruction_read_single_bank(1);
|
||||||
|
pim_matrix_arena1
|
||||||
|
.borrow()
|
||||||
|
.execute_instruction_read_single_bank(2);
|
||||||
|
pim_matrix_arena1
|
||||||
|
.borrow()
|
||||||
|
.execute_instruction_read_single_bank(3);
|
||||||
|
pim_matrix_arena1
|
||||||
|
.borrow()
|
||||||
|
.execute_instruction_read_single_bank(4);
|
||||||
|
pim_matrix_arena1
|
||||||
|
.borrow()
|
||||||
|
.execute_instruction_read_single_bank(5);
|
||||||
|
pim_matrix_arena1
|
||||||
|
.borrow()
|
||||||
|
.execute_instruction_read_single_bank(6);
|
||||||
|
pim_matrix_arena1
|
||||||
|
.borrow()
|
||||||
|
.execute_instruction_read_single_bank(7);
|
||||||
|
|
||||||
|
pim_matrix_arena2
|
||||||
|
.borrow_mut()
|
||||||
|
.execute_instruction_write_single_bank(0);
|
||||||
|
pim_matrix_arena2
|
||||||
|
.borrow_mut()
|
||||||
|
.execute_instruction_write_single_bank(1);
|
||||||
|
pim_matrix_arena2
|
||||||
|
.borrow_mut()
|
||||||
|
.execute_instruction_write_single_bank(2);
|
||||||
|
pim_matrix_arena2
|
||||||
|
.borrow_mut()
|
||||||
|
.execute_instruction_write_single_bank(3);
|
||||||
|
pim_matrix_arena2
|
||||||
|
.borrow_mut()
|
||||||
|
.execute_instruction_write_single_bank(4);
|
||||||
|
pim_matrix_arena2
|
||||||
|
.borrow_mut()
|
||||||
|
.execute_instruction_write_single_bank(5);
|
||||||
|
pim_matrix_arena2
|
||||||
|
.borrow_mut()
|
||||||
|
.execute_instruction_write_single_bank(6);
|
||||||
|
pim_matrix_arena2
|
||||||
|
.borrow_mut()
|
||||||
|
.execute_instruction_write_single_bank(7);
|
||||||
|
|
||||||
|
dummy_array.execute_instruction_read_single_bank(0);
|
||||||
|
|
||||||
|
pim_state.set_bank_mode(BankMode::SingleBank);
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,10 +27,21 @@ impl PimState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.writer.write(
|
||||||
|
serde_json_core::to_string::<PimConfig, 64>(&PimConfig {
|
||||||
|
kernel: None,
|
||||||
|
bank_mode: Some(bank_mode),
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.as_str(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_kernel(&mut self) {
|
||||||
self.writer.write(
|
self.writer.write(
|
||||||
serde_json_core::to_string::<PimConfig, 2048>(&PimConfig {
|
serde_json_core::to_string::<PimConfig, 2048>(&PimConfig {
|
||||||
kernel: self.kernel.clone(),
|
kernel: Some(self.kernel.clone()),
|
||||||
bank_mode,
|
bank_mode: None,
|
||||||
})
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.as_str(),
|
.as_str(),
|
||||||
|
|||||||
@@ -63,9 +63,22 @@ impl core::ops::MulAssign<F16x1> for F16x1 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Default, Clone, Copy, Debug, PartialEq)]
|
#[derive(Default, Clone, Copy, PartialEq)]
|
||||||
pub struct F16x16(pub [F16x1; FLOATING_POINT_UNITS]);
|
pub struct F16x16(pub [F16x1; FLOATING_POINT_UNITS]);
|
||||||
|
|
||||||
|
// TODO remove
|
||||||
|
impl core::fmt::Debug for F16x16 {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
self.0[0].fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl core::fmt::Display for F16x16 {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
self.0[0].fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl num_traits::identities::Zero for F16x16 {
|
impl num_traits::identities::Zero for F16x16 {
|
||||||
fn zero() -> Self {
|
fn zero() -> Self {
|
||||||
Self([F16x1::zero(); FLOATING_POINT_UNITS])
|
Self([F16x1::zero(); FLOATING_POINT_UNITS])
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use half::f16;
|
use half::f16;
|
||||||
use pim_isa::{BankMode, File, Instruction, Kernel, PimConfig};
|
use pim_isa::{BankMode, File, Instruction, Kernel};
|
||||||
|
|
||||||
#[cxx::bridge(namespace = "pim_vm")]
|
#[cxx::bridge(namespace = "pim_vm")]
|
||||||
mod ffi {
|
mod ffi {
|
||||||
@@ -64,7 +64,8 @@ impl Default for PimUnit {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct PimVM {
|
struct PimVM {
|
||||||
pim_units: Vec<PimUnit>,
|
pim_units: Vec<PimUnit>,
|
||||||
pim_config: pim_isa::PimConfig,
|
bank_mode: pim_isa::BankMode,
|
||||||
|
kernel: pim_isa::Kernel,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PimVM {
|
impl PimVM {
|
||||||
@@ -76,16 +77,19 @@ impl PimVM {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn apply_config(&mut self, config_str: &str) {
|
fn apply_config(&mut self, config_str: &str) {
|
||||||
log::debug!("Config string:\n{config_str}");
|
let config = serde_json::from_str::<pim_isa::PimConfig>(config_str).unwrap();
|
||||||
|
|
||||||
self.pim_config = serde_json::from_str::<pim_isa::PimConfig>(config_str).unwrap();
|
if let Some(kernel) = config.kernel {
|
||||||
self.reset();
|
self.kernel = kernel;
|
||||||
|
}
|
||||||
|
|
||||||
log::debug!("Apply pim config:\n{:?}", self.pim_config);
|
if let Some(bank_mode) = config.bank_mode {
|
||||||
|
self.bank_mode = bank_mode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bank_mode(&self) -> ffi::BankMode {
|
fn bank_mode(&self) -> ffi::BankMode {
|
||||||
match self.pim_config.bank_mode {
|
match self.bank_mode {
|
||||||
BankMode::SingleBank => ffi::BankMode::SingleBank,
|
BankMode::SingleBank => ffi::BankMode::SingleBank,
|
||||||
BankMode::AllBank => ffi::BankMode::AllBank,
|
BankMode::AllBank => ffi::BankMode::AllBank,
|
||||||
BankMode::PimAllBank => ffi::BankMode::PimAllBank,
|
BankMode::PimAllBank => ffi::BankMode::PimAllBank,
|
||||||
@@ -102,10 +106,8 @@ fn new_pim_vm(num_banks: u32) -> Box<PimVM> {
|
|||||||
|
|
||||||
Box::new(PimVM {
|
Box::new(PimVM {
|
||||||
pim_units: vec![PimUnit::default(); num_pim_units as _],
|
pim_units: vec![PimUnit::default(); num_pim_units as _],
|
||||||
pim_config: PimConfig {
|
bank_mode: BankMode::SingleBank,
|
||||||
bank_mode: BankMode::SingleBank,
|
kernel: Kernel::NOP,
|
||||||
kernel: Kernel::NOP,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,12 +126,14 @@ impl PimVM {
|
|||||||
|
|
||||||
let pim_unit = &mut self.pim_units[pim_unit_index as usize];
|
let pim_unit = &mut self.pim_units[pim_unit_index as usize];
|
||||||
|
|
||||||
let mut inst = self.pim_config.kernel.0[pim_unit.pc as usize];
|
let mut inst = self.kernel.0[pim_unit.pc as usize];
|
||||||
|
|
||||||
log::debug!(
|
if pim_unit_index == 0 {
|
||||||
"PimUnit {pim_unit_index} Execute PC {}: {inst:?}",
|
log::debug!(
|
||||||
pim_unit.pc
|
"PimUnit {pim_unit_index} Execute PC {}: {inst:?}",
|
||||||
);
|
pim_unit.pc
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
pim_unit.pc += 1;
|
pim_unit.pc += 1;
|
||||||
|
|
||||||
@@ -151,10 +155,12 @@ impl PimVM {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pim_unit.pc = new_pc as _;
|
pim_unit.pc = new_pc as _;
|
||||||
log::debug!("PimUnit {pim_unit_index} New PC {new_pc}: {inst:?}");
|
if pim_unit_index == 0 {
|
||||||
|
log::debug!("PimUnit {pim_unit_index} New PC {new_pc}: {inst:?}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inst = self.pim_config.kernel.0[pim_unit.pc as usize];
|
inst = self.kernel.0[pim_unit.pc as usize];
|
||||||
pim_unit.pc += 1;
|
pim_unit.pc += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,7 +311,16 @@ impl PimVM {
|
|||||||
.try_into()
|
.try_into()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
log::debug!("{data0:?}, {data1:?}, {data2:?}, {product:?}, {sum:?}");
|
if pim_unit_index == 0 {
|
||||||
|
log::debug!(
|
||||||
|
"\n{:?}\n{:?}\n{:?}\n{:?}\n{:?}",
|
||||||
|
data0[0],
|
||||||
|
data1[0],
|
||||||
|
data2[0],
|
||||||
|
product[0],
|
||||||
|
sum[0]
|
||||||
|
);
|
||||||
|
}
|
||||||
PimVM::store(dst, pim_unit, &sum);
|
PimVM::store(dst, pim_unit, &sum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -323,10 +338,11 @@ impl PimVM {
|
|||||||
let current_pc = pim_unit.pc;
|
let current_pc = pim_unit.pc;
|
||||||
pim_unit.pc += 1;
|
pim_unit.pc += 1;
|
||||||
|
|
||||||
let inst = &self.pim_config.kernel.0[current_pc as usize];
|
let inst = &self.kernel.0[current_pc as usize];
|
||||||
|
|
||||||
log::debug!("PimUnit {pim_unit_index} Execute PC {current_pc}: {inst:?}");
|
|
||||||
|
|
||||||
|
if pim_unit_index == 0 {
|
||||||
|
log::debug!("PimUnit {pim_unit_index} Execute PC {current_pc}: {inst:?}");
|
||||||
|
}
|
||||||
let data = match inst {
|
let data = match inst {
|
||||||
Instruction::FILL { src, dst } => {
|
Instruction::FILL { src, dst } => {
|
||||||
let data: [f16; FP_UNITS] = match src {
|
let data: [f16; FP_UNITS] = match src {
|
||||||
@@ -339,7 +355,9 @@ impl PimVM {
|
|||||||
panic!("Unsupported dst operand: {dst:?}")
|
panic!("Unsupported dst operand: {dst:?}")
|
||||||
}
|
}
|
||||||
|
|
||||||
log::debug!("Store {data:?}");
|
if pim_unit_index == 0 {
|
||||||
|
log::debug!("Store {data:?}");
|
||||||
|
}
|
||||||
|
|
||||||
data
|
data
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user