pims-simulator symlink memory opt

This commit is contained in:
ilgeco
2026-04-21 15:43:10 +02:00
parent f4c6da8f10
commit 0368f96593
9 changed files with 182 additions and 167 deletions

View File

@@ -38,14 +38,14 @@ impl Crossbar {
self.memory.execute_store(0, element)
}
pub fn load<T>(&mut self, size: usize) -> Result<Vec<&[T]>> where
pub fn load<T>(&self, size: usize) -> Result<Vec<&[T]>> where
T: MemoryStorable, {
if self.memory.get_len() < size
//|| self.stored_bytes < size
{
bail!("Loading outside crossbar boundary [{} {}] < {}", self.stored_bytes, self.memory.get_len() , size);
}
self.memory.load(0, size)
self.memory.load_const(0, size)
}

View File

@@ -1,5 +1,5 @@
use std::{collections::HashMap, fmt::Debug};
use anyhow::{Context, Result};
use anyhow::{Context, Result, ensure};
use crate::{
cpu::crossbar::Crossbar,
@@ -10,53 +10,44 @@ use crate::{
pub mod crossbar;
#[derive(Debug, Clone)]
pub struct CPU {
cores: Box<[Core]>,
pub struct CPU<'a> {
cores: Box<[Core<'a>]>,
}
impl CPU {
pub fn new(num_cores: impl TryToUsize) -> Self {
impl<'a> CPU<'a> {
pub fn new(num_cores: impl TryToUsize, crossbars: Vec<Vec<&'a Crossbar>> ) -> Self {
let num_cores = num_cores.try_into().expect("num_cores can not be negative");
let mut cores: Vec<Core> = std::iter::repeat_with(Core::new)
.take(num_cores + 1)
.collect();
assert!(crossbars.len() == num_cores + 1);
let mut cores = Vec::new();
for crossbar in crossbars {
cores.push(Core::new(crossbar));
}
Self {
cores: cores.into(),
}
}
pub fn reserve_crossbar(
&mut self,
num_crossbar: impl TryToUsize,
byte_width: impl TryToUsize,
height: impl TryToUsize,
) {
let num_crossbar = num_crossbar
.try_into()
.expect("num_crossbar can not be negative");
let byte_width = byte_width
.try_into()
.expect("byte_width can not be negative");
let height = height.try_into().expect("height can not be negative");
for core in &mut self.cores {
core.reserve_crossbar(num_crossbar, byte_width, height);
}
pub fn host<'b>(&'b mut self) -> &'b mut Core<'a>
where 'a : 'b
{
& mut self.cores[0]
}
pub fn host(&mut self) -> &mut Core {
&mut self.cores[0]
}
pub fn core(&mut self, index: impl TryToUsize) -> &mut Core {
pub fn core<'b >(&'b mut self, index: impl TryToUsize) -> &'b mut Core<'a>
where 'a : 'b
{
let index = index.try_into().expect("can not be negative");
&mut self.cores[index]
& mut self.cores[index]
}
pub fn num_core(&self) -> usize {
self.cores.len()
}
pub(crate) fn host_and_cores(&mut self, core: impl TryToUsize) -> (&mut Core, &mut Core) {
pub(crate) fn host_and_cores<'b, 'c >(&'b mut self, core: impl TryToUsize) -> (&'c mut Core<'a>, &'c mut Core<'a>)
where 'a: 'b,
'b: 'c
{
let core = core.try_into().expect("core can not be negative");
assert_ne!(
core, 0,
@@ -70,45 +61,29 @@ impl CPU {
(host, core)
}
pub fn get_multiple_cores<const N: usize>(&mut self, indices: [usize; N]) -> [&mut Core; N] {
pub fn get_multiple_cores<'b, const N: usize>(&'b mut self, indices: [usize; N]) -> [&'b mut Core<'a>; N]
where 'a : 'b
{
self.cores.get_disjoint_mut(indices).unwrap()
}
}
#[derive(Debug, Clone)]
pub struct Core {
crossbars: Vec<Crossbar>,
pub struct Core<'a> {
crossbars: Vec<&'a Crossbar>,
memory: CoreMemory,
registers: [i32; 32],
}
impl Core {
fn new() -> Self {
impl<'a> Core<'a> {
fn new(crossbars : Vec<&'a Crossbar>) -> Self {
Self {
crossbars: Vec::new(),
crossbars,
memory: CoreMemory::new(),
registers: [0; 32],
}
}
pub fn reserve_crossbar(
&mut self,
num_crossbar: impl TryToUsize,
width: impl TryToUsize,
height: impl TryToUsize,
) {
let num_crossbar = num_crossbar
.try_into()
.expect("num_crossbar can not be negative");
let width = width.try_into().expect("width can not be negative");
let height = height.try_into().expect("height can not be negative");
for _ in 0..num_crossbar {
let mut crossbar = CoreMemory::new();
crossbar.set_capacity(width * height);
self.crossbars.push(Crossbar::new(width, height, crossbar));
}
}
pub fn execute_load<T>(&mut self) -> Result<Vec<&[T]>>
where
T: MemoryStorable,
@@ -157,7 +132,7 @@ impl Core {
self.memory.load(address, size)
}
pub fn get_memory_crossbar(&mut self) -> (&mut CoreMemory, &mut Vec<Crossbar>) {
pub fn get_memory_crossbar(&mut self) -> (&mut CoreMemory, &mut Vec<&'a Crossbar>) {
let Self {
crossbars,
memory,

View File

@@ -76,7 +76,8 @@ pub fn functor_to_name(functor: usize) -> &'static str {
///////////////////////////////////////////////////////////////
/////////////////Scalar/register Instructions//////////////////
///////////////////////////////////////////////////////////////
pub fn sldi(cores: &mut CPU, data: InstructionData) -> Result<InstructionStatus> {
pub fn sldi(cores: &mut CPU, data: InstructionData) -> Result<InstructionStatus>
{
TRACER.lock().unwrap().pre_sldi(cores, data);
let (core_indx, rd, imm) = data.get_core_rd_imm();
let core = cores.core(core_indx);

View File

@@ -40,7 +40,9 @@ impl Instruction {
Self { data, functor }
}
pub fn execute(&self, cpu: &mut CPU) -> InstructionStatus {
pub fn execute<'a, 'b>(&'b self, cpu: &mut CPU<'a>) -> InstructionStatus
where 'a : 'b
{
(self.functor)(cpu, self.data)
.with_context(|| format!("Instruction: {}", functor_to_name(self.functor as usize)))
.with_context(|| format!("Error in core: {}", self.data.core_indx() - 1))

View File

@@ -1,10 +1,11 @@
use core::panic;
use std::collections::HashMap;
use serde_json::{Map, Value};
use crate::{
CoreInstructionsBuilder, Executable,
cpu::{CPU, crossbar},
cpu::{CPU, crossbar::{self, Crossbar}},
instruction_set::{
InstructionsBuilder,
instruction_data::{self, InstructionData, InstructionDataBuilder},
@@ -13,18 +14,20 @@ use crate::{
memory_manager::type_traits::TryToUsize,
};
pub fn json_to_executor<'a>(
config: Value,
mut cores: impl Iterator<Item = &'a Value>,
) -> Executable {
crossbars : Vec<Vec<&'a Crossbar>>
) -> Executable<'a> {
let cell_precision = config.get("cell_precision").unwrap().as_i64().unwrap() as i32;
let core_cnt = config.get("core_cnt").unwrap().as_i64().unwrap() as i32 - 1;
let xbar_count = config.get("xbar_array_count").unwrap().as_i64().unwrap() as i32;
let xbar_size = config.get("xbar_size").unwrap().as_array().unwrap();
let rows_crossbar = xbar_size[0].as_i64().unwrap() as i32;
let column_corssbar = xbar_size[1].as_i64().unwrap() as i32;
let mut cpu = CPU::new(core_cnt);
cpu.reserve_crossbar(xbar_count, column_corssbar * 4, rows_crossbar);
let mut cpu = CPU::new(core_cnt, crossbars);
let mut core_insts_builder = CoreInstructionsBuilder::new(core_cnt as usize);
cores.next();
for core_indx in 1..=core_cnt {

View File

@@ -111,6 +111,24 @@ where {
Ok(res)
}
pub fn load_const<T>(&self, address: impl TryToUsize, size: impl TryToUsize) -> Result<Vec<&[T]>>
where
T: MemoryStorable,
{
let address = address.try_into().expect("address can not be negative");
let size = size.try_into().expect("size can not be negative");
let Self {
memory,
load_requests,
} = self;
let mut res = Vec::new();
let memory_slice = &memory[address..address + size];
let memory_slice = unsafe { slice_from_u8(memory_slice) }
.with_context(|| format!("Accessing from {} to {}", address, address + size))?;
res.push(memory_slice);
Ok(res)
}
pub fn load<T>(&mut self, address: impl TryToUsize, size: impl TryToUsize) -> Result<Vec<&[T]>>
where
T: MemoryStorable,

View File

@@ -67,14 +67,14 @@ impl From<Instructions> for CoreInstruction {
}
#[derive(Debug, Clone)]
pub struct Executable {
cpu: CPU,
pub struct Executable<'a> {
cpu: CPU<'a>,
core_instructions: Vec<CoreInstruction>,
send_recv : SendRecv,
}
impl Executable {
pub fn new(cpu: CPU, core_instructions: Vec<CoreInstruction>) -> Self {
impl<'a> Executable<'a> {
pub fn new(cpu: CPU<'a>, core_instructions: Vec<CoreInstruction>) -> Executable<'a> {
let num_core = cpu.num_core();
let send_recv = SendRecv::new(num_core);
assert_eq!(num_core, core_instructions.len(), "Some core doesn't have is list of istruction (required even if empty)");
@@ -85,12 +85,14 @@ impl Executable {
}
}
pub fn execute(&mut self) {
pub fn execute<'b>(&'b mut self)
where 'a : 'b
{
let Self {
cpu,
cpu ,
core_instructions,
send_recv
} = self;
} = self;
let mut cpu_progressed = 0;
let max_core = cpu.num_core();
let mut index_unit = 0;
@@ -124,11 +126,11 @@ impl Executable {
}
}
pub fn cpu(&self) -> &CPU {
pub fn cpu(&self) -> &CPU<'a> {
&self.cpu
}
pub fn cpu_mut(&mut self) -> &mut CPU {
pub fn cpu_mut(&mut self) -> &mut CPU<'a> {
&mut self.cpu
}
@@ -143,64 +145,13 @@ impl Executable {
}
}
fn handle_wait_sync(cpu: &mut CPU, core_instructions: &mut [CoreInstruction], core_result: InstructionStatus) {
fn handle_wait_sync<'a, 'b, 'c >(cpu: &'b mut CPU<'a>, core_instructions: &'c mut [CoreInstruction], core_result: InstructionStatus)
where 'a : 'b,
'a : 'c
{
}
#[cfg(test)]
mod test {
use super::*;
use crate::instruction_set::instruction_data::InstructionDataBuilder;
use crate::instruction_set::{InstructionsBuilder, isa::*};
#[test]
fn test_only_host() {
let mut cpu = CPU::new(0);
cpu.host()
.execute_store(0, &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
let mut inst_builder = InstructionsBuilder::new();
let mut idata_build = InstructionDataBuilder::new();
idata_build.set_core_indx(0).fix_core_indx();
inst_builder.make_inst(sldi, idata_build.set_rdimm(1, 0).build());
inst_builder.make_inst(sld, idata_build.set_rdr1(1, 1).build());
inst_builder.make_inst(sldi, idata_build.set_rdimm(2, 8).build());
inst_builder.make_inst(sld, idata_build.set_rdr1(2, 2).build());
inst_builder.make_inst(sadd, idata_build.set_rdr1r2(2, 1, 2).build());
let mut core_instruction = vec![inst_builder.build().into()];
let mut executable = Executable::new(cpu, core_instruction);
executable.execute();
assert_eq!(executable.cpu_mut().host().register(2), 4, "Not sum to 4");
}
#[test]
fn test_10_core_same_code() {
let setup_core = |index: usize, cpu: &mut CPU| -> Instructions {
cpu.core(index)
.execute_store(0, &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]);
let mut inst_builder = InstructionsBuilder::new();
let mut idata_build = InstructionDataBuilder::new();
idata_build.set_core_indx(index as i32).fix_core_indx();
inst_builder.make_inst(sldi, idata_build.set_rdimm(1, 0).build());
inst_builder.make_inst(sld, idata_build.set_rdr1(1, 1).build());
inst_builder.make_inst(sldi, idata_build.set_rdimm(2, 8).build());
inst_builder.make_inst(sld, idata_build.set_rdr1(2, 2).build());
inst_builder.make_inst(sadd, idata_build.set_rdr1r2(2, 1, 2).build());
inst_builder.build()
};
let mut cpu = CPU::new(10);
let mut core_instruction = Vec::new();
for i in 0..cpu.num_core() {
core_instruction.push(setup_core(i, &mut cpu).into())
}
let mut executable = Executable::new(cpu, core_instruction);
executable.execute();
for i in 0.. executable.cpu.num_core() {
assert_eq!(executable.cpu_mut().core(i).register(2), 4, "Core {} not sum to 4", i);
}
}
}

View File

@@ -41,14 +41,16 @@ impl SendRecv {
}
}
pub fn handle_send_recv(
cpu: &mut CPU,
core_instructions: &mut [CoreInstruction],
send_recv: &mut SendRecv,
pub fn handle_send_recv<'a, 'b >(
cpu: &'b mut CPU<'a>,
core_instructions: & mut [CoreInstruction],
send_recv: & mut SendRecv,
core_result: InstructionStatus,
) -> bool {
let transfer_memory = |cpu: &mut CPU,
core_instructions: &mut [CoreInstruction],
) -> bool
where 'a : 'b
{
let transfer_memory = |cpu: &'b mut CPU<'a>,
core_instructions: & mut [CoreInstruction],
sender: Option<SendRecvInfo>,
receiver: Option<SendRecvInfo>| {
if let Some(sender) = sender
@@ -117,7 +119,7 @@ pub fn handle_send_recv(
send_recv.sending[sender] = None;
send_recv.receiving[receiver] = None;
}
return transfered;
transfered
}
InstructionStatus::Reciving(instruction_data) => {
let (core_idx, imm_core) = instruction_data.get_core_immcore();
@@ -146,7 +148,7 @@ pub fn handle_send_recv(
send_recv.sending[sender] = None;
send_recv.receiving[receiver] = None;
}
return transfered;
transfered
}
_ => false,
}