pims-simulator symlink memory opt
This commit is contained in:
@@ -1,10 +1,13 @@
|
|||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{Context, Result, bail};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use glob::glob;
|
use glob::glob;
|
||||||
|
use pimcore::cpu::crossbar::Crossbar;
|
||||||
use pimcore::json_to_instruction::json_to_executor;
|
use pimcore::json_to_instruction::json_to_executor;
|
||||||
|
use pimcore::memory_manager::CoreMemory;
|
||||||
use pimcore::tracing::TRACER;
|
use pimcore::tracing::TRACER;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::fs;
|
use std::collections::HashMap;
|
||||||
|
use std::fs::{self, read_link};
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
@@ -43,8 +46,10 @@ fn main() -> Result<()> {
|
|||||||
let config_json = retrive_config(&args)?;
|
let config_json = retrive_config(&args)?;
|
||||||
let core_jsons = retrive_cores(&args)?;
|
let core_jsons = retrive_cores(&args)?;
|
||||||
let memory = retrive_memory(&args)?;
|
let memory = retrive_memory(&args)?;
|
||||||
let mut executor = json_to_executor::json_to_executor(config_json, core_jsons.iter());
|
let global_crossbars = get_crossbars(&config_json, &args).unwrap();
|
||||||
populate_crossbar(&args, &mut executor);
|
let crossbars = map_crossbars_to_cores(&config_json, &args, &global_crossbars);
|
||||||
|
let mut executor =
|
||||||
|
json_to_executor::json_to_executor(config_json, core_jsons.iter(), crossbars);
|
||||||
set_memory(&mut executor, memory);
|
set_memory(&mut executor, memory);
|
||||||
TRACER
|
TRACER
|
||||||
.lock()
|
.lock()
|
||||||
@@ -55,46 +60,100 @@ fn main() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn populate_crossbar(args: &Args, executor: &mut pimcore::Executable) {
|
fn map_crossbars_to_cores<'c>(
|
||||||
let num_cores = executor.cpu_mut().num_core();
|
config: &Value,
|
||||||
|
args: &Args,
|
||||||
|
global_crossbars: &'c HashMap<String, Crossbar>,
|
||||||
|
) -> Vec<Vec<&'c Crossbar>> {
|
||||||
|
let mut res = Vec::new();
|
||||||
|
let num_cores = config.get("core_cnt").unwrap().as_i64().unwrap() as i32;
|
||||||
|
|
||||||
if let Some(folder) = args.folder.as_ref() {
|
if let Some(folder) = args.folder.as_ref() {
|
||||||
for core_idx in 0..num_cores {
|
for core_idx in 0..num_cores {
|
||||||
let core_folder = folder.join(format!("core_{}", core_idx));
|
let core_folder = folder.join(format!("core_{}", core_idx));
|
||||||
|
res.push(Vec::new());
|
||||||
|
|
||||||
if !core_folder.is_dir() {
|
if !core_folder.is_dir() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut bin_files: Vec<(u32, std::path::PathBuf)> = std::fs::read_dir(&core_folder)
|
let mut sym_link_files: Vec<(u32, std::path::PathBuf)> =
|
||||||
.expect("Failed to read core directory")
|
std::fs::read_dir(&core_folder)
|
||||||
.filter_map(|entry| {
|
.expect("Failed to read core directory")
|
||||||
let path = entry.ok()?.path();
|
.filter_map(|entry| {
|
||||||
let file_name = path.file_name()?.to_str()?;
|
let entry = entry.ok()?;
|
||||||
|
assert!(entry.metadata().unwrap().is_symlink());
|
||||||
|
let path = entry.path();
|
||||||
|
let file_name = path.file_name()?.to_str()?;
|
||||||
|
|
||||||
if file_name.starts_with("crossbar_") && file_name.ends_with(".bin") {
|
if file_name.starts_with("crossbar_") && file_name.ends_with(".bin") {
|
||||||
let num_str = &file_name[9..file_name.len() - 4];
|
let num_str = &file_name[9..file_name.len() - 4];
|
||||||
let num = num_str.parse::<u32>().ok()?;
|
let num = num_str.parse::<u32>().ok()?;
|
||||||
Some((num, path))
|
Some((num, path))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
bin_files.sort_by_key(|&(num, _)| num);
|
sym_link_files.sort_by_key(|&(num, _)| num);
|
||||||
let core = executor.cpu_mut().core(core_idx);
|
|
||||||
let (_memory, crossbars) = core.get_memory_crossbar();
|
|
||||||
|
|
||||||
for (i, path) in bin_files {
|
for (_, symlink) in sym_link_files {
|
||||||
let bytes = std::fs::read(path).expect("Failed to read binary file");
|
let real_path = read_link(symlink).unwrap();
|
||||||
crossbars
|
let path_as_str = real_path.to_str().unwrap();
|
||||||
.get_mut(i as usize)
|
assert!(
|
||||||
|
global_crossbars.contains_key(path_as_str),
|
||||||
|
"symlink point to {:?}\n a not stored crossbar",
|
||||||
|
real_path
|
||||||
|
);
|
||||||
|
|
||||||
|
res.iter_mut()
|
||||||
|
.next_back()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.execute_store(&bytes)
|
.push(global_crossbars.get(path_as_str).unwrap());
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_crossbars(config: &Value, args: &Args) -> anyhow::Result<HashMap<String, Crossbar>> {
|
||||||
|
let xbar_size = config.get("xbar_size").unwrap().as_array().unwrap();
|
||||||
|
let rows_crossbar = xbar_size[0].as_i64().unwrap() as usize;
|
||||||
|
let column_corssbar = xbar_size[1].as_i64().unwrap() as usize;
|
||||||
|
let mut res = HashMap::new();
|
||||||
|
|
||||||
|
if let Some(folder) = args.folder.as_ref() {
|
||||||
|
let weight_folder = folder.join("weights");
|
||||||
|
if !weight_folder.is_dir() {
|
||||||
|
bail!("Not a directory");
|
||||||
|
}
|
||||||
|
for weight_file in
|
||||||
|
std::fs::read_dir(&weight_folder).context("Weight folder not iterable")?
|
||||||
|
{
|
||||||
|
let weight_file = weight_file.context("File not iterable")?;
|
||||||
|
if weight_file
|
||||||
|
.metadata()
|
||||||
|
.context("Doesn't contain metadata")?
|
||||||
|
.is_dir()
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let bytes = std::fs::read(weight_file.path()).expect("Failed to read binary file");
|
||||||
|
let mut crossbar =
|
||||||
|
Crossbar::new(column_corssbar * 4, rows_crossbar, CoreMemory::new());
|
||||||
|
crossbar.execute_store(&bytes).unwrap();
|
||||||
|
res.insert(
|
||||||
|
weight_file
|
||||||
|
.path()
|
||||||
|
.to_str()
|
||||||
|
.context("file name not utf-8")?
|
||||||
|
.to_string(),
|
||||||
|
crossbar,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dump_memory(mut executor: pimcore::Executable, args: &Args) -> Result<()> {
|
fn dump_memory(mut executor: pimcore::Executable, args: &Args) -> Result<()> {
|
||||||
@@ -170,7 +229,11 @@ fn retrive_cores(args: &Args) -> Result<Vec<Value>, anyhow::Error> {
|
|||||||
let pattern_str = pattern.to_str().context("Invalid path encoding")?;
|
let pattern_str = pattern.to_str().context("Invalid path encoding")?;
|
||||||
let mut paths: Vec<_> = glob(pattern_str)?.map(|x| x.unwrap()).collect();
|
let mut paths: Vec<_> = glob(pattern_str)?.map(|x| x.unwrap()).collect();
|
||||||
paths.sort_by_cached_key(|x| {
|
paths.sort_by_cached_key(|x| {
|
||||||
let mut x = x.file_stem().expect("Extracting the stem").to_str().expect("File not utf-8");
|
let mut x = x
|
||||||
|
.file_stem()
|
||||||
|
.expect("Extracting the stem")
|
||||||
|
.to_str()
|
||||||
|
.expect("File not utf-8");
|
||||||
x = &x[5..];
|
x = &x[5..];
|
||||||
x.parse::<i32>().unwrap()
|
x.parse::<i32>().unwrap()
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -38,14 +38,14 @@ impl Crossbar {
|
|||||||
self.memory.execute_store(0, element)
|
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, {
|
T: MemoryStorable, {
|
||||||
if self.memory.get_len() < size
|
if self.memory.get_len() < size
|
||||||
//|| self.stored_bytes < size
|
//|| self.stored_bytes < size
|
||||||
{
|
{
|
||||||
bail!("Loading outside crossbar boundary [{} {}] < {}", self.stored_bytes, self.memory.get_len() , 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use std::{collections::HashMap, fmt::Debug};
|
use std::{collections::HashMap, fmt::Debug};
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result, ensure};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
cpu::crossbar::Crossbar,
|
cpu::crossbar::Crossbar,
|
||||||
@@ -10,53 +10,44 @@ use crate::{
|
|||||||
pub mod crossbar;
|
pub mod crossbar;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct CPU {
|
pub struct CPU<'a> {
|
||||||
cores: Box<[Core]>,
|
cores: Box<[Core<'a>]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CPU {
|
impl<'a> CPU<'a> {
|
||||||
pub fn new(num_cores: impl TryToUsize) -> Self {
|
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 num_cores = num_cores.try_into().expect("num_cores can not be negative");
|
||||||
let mut cores: Vec<Core> = std::iter::repeat_with(Core::new)
|
assert!(crossbars.len() == num_cores + 1);
|
||||||
.take(num_cores + 1)
|
let mut cores = Vec::new();
|
||||||
.collect();
|
for crossbar in crossbars {
|
||||||
|
cores.push(Core::new(crossbar));
|
||||||
|
}
|
||||||
Self {
|
Self {
|
||||||
cores: cores.into(),
|
cores: cores.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reserve_crossbar(
|
pub fn host<'b>(&'b mut self) -> &'b mut Core<'a>
|
||||||
&mut self,
|
where 'a : 'b
|
||||||
num_crossbar: impl TryToUsize,
|
{
|
||||||
byte_width: impl TryToUsize,
|
& mut self.cores[0]
|
||||||
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(&mut self) -> &mut Core {
|
pub fn core<'b >(&'b mut self, index: impl TryToUsize) -> &'b mut Core<'a>
|
||||||
&mut self.cores[0]
|
where 'a : 'b
|
||||||
}
|
{
|
||||||
|
|
||||||
pub fn core(&mut self, index: impl TryToUsize) -> &mut Core {
|
|
||||||
let index = index.try_into().expect("can not be negative");
|
let index = index.try_into().expect("can not be negative");
|
||||||
&mut self.cores[index]
|
& mut self.cores[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn num_core(&self) -> usize {
|
pub fn num_core(&self) -> usize {
|
||||||
self.cores.len()
|
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");
|
let core = core.try_into().expect("core can not be negative");
|
||||||
assert_ne!(
|
assert_ne!(
|
||||||
core, 0,
|
core, 0,
|
||||||
@@ -70,45 +61,29 @@ impl CPU {
|
|||||||
(host, core)
|
(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()
|
self.cores.get_disjoint_mut(indices).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Core {
|
pub struct Core<'a> {
|
||||||
crossbars: Vec<Crossbar>,
|
crossbars: Vec<&'a Crossbar>,
|
||||||
memory: CoreMemory,
|
memory: CoreMemory,
|
||||||
registers: [i32; 32],
|
registers: [i32; 32],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Core {
|
impl<'a> Core<'a> {
|
||||||
fn new() -> Self {
|
fn new(crossbars : Vec<&'a Crossbar>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
crossbars: Vec::new(),
|
crossbars,
|
||||||
memory: CoreMemory::new(),
|
memory: CoreMemory::new(),
|
||||||
registers: [0; 32],
|
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]>>
|
pub fn execute_load<T>(&mut self) -> Result<Vec<&[T]>>
|
||||||
where
|
where
|
||||||
T: MemoryStorable,
|
T: MemoryStorable,
|
||||||
@@ -157,7 +132,7 @@ impl Core {
|
|||||||
self.memory.load(address, size)
|
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 {
|
let Self {
|
||||||
crossbars,
|
crossbars,
|
||||||
memory,
|
memory,
|
||||||
|
|||||||
@@ -76,7 +76,8 @@ pub fn functor_to_name(functor: usize) -> &'static str {
|
|||||||
///////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////
|
||||||
/////////////////Scalar/register Instructions//////////////////
|
/////////////////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);
|
TRACER.lock().unwrap().pre_sldi(cores, data);
|
||||||
let (core_indx, rd, imm) = data.get_core_rd_imm();
|
let (core_indx, rd, imm) = data.get_core_rd_imm();
|
||||||
let core = cores.core(core_indx);
|
let core = cores.core(core_indx);
|
||||||
|
|||||||
@@ -40,7 +40,9 @@ impl Instruction {
|
|||||||
Self { data, functor }
|
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)
|
(self.functor)(cpu, self.data)
|
||||||
.with_context(|| format!("Instruction: {}", functor_to_name(self.functor as usize)))
|
.with_context(|| format!("Instruction: {}", functor_to_name(self.functor as usize)))
|
||||||
.with_context(|| format!("Error in core: {}", self.data.core_indx() - 1))
|
.with_context(|| format!("Error in core: {}", self.data.core_indx() - 1))
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
use core::panic;
|
use core::panic;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use serde_json::{Map, Value};
|
use serde_json::{Map, Value};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
CoreInstructionsBuilder, Executable,
|
CoreInstructionsBuilder, Executable,
|
||||||
cpu::{CPU, crossbar},
|
cpu::{CPU, crossbar::{self, Crossbar}},
|
||||||
instruction_set::{
|
instruction_set::{
|
||||||
InstructionsBuilder,
|
InstructionsBuilder,
|
||||||
instruction_data::{self, InstructionData, InstructionDataBuilder},
|
instruction_data::{self, InstructionData, InstructionDataBuilder},
|
||||||
@@ -13,18 +14,20 @@ use crate::{
|
|||||||
memory_manager::type_traits::TryToUsize,
|
memory_manager::type_traits::TryToUsize,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
pub fn json_to_executor<'a>(
|
pub fn json_to_executor<'a>(
|
||||||
config: Value,
|
config: Value,
|
||||||
mut cores: impl Iterator<Item = &'a 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 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 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_count = config.get("xbar_array_count").unwrap().as_i64().unwrap() as i32;
|
||||||
let xbar_size = config.get("xbar_size").unwrap().as_array().unwrap();
|
let xbar_size = config.get("xbar_size").unwrap().as_array().unwrap();
|
||||||
let rows_crossbar = xbar_size[0].as_i64().unwrap() as i32;
|
let rows_crossbar = xbar_size[0].as_i64().unwrap() as i32;
|
||||||
let column_corssbar = xbar_size[1].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);
|
let mut core_insts_builder = CoreInstructionsBuilder::new(core_cnt as usize);
|
||||||
cores.next();
|
cores.next();
|
||||||
for core_indx in 1..=core_cnt {
|
for core_indx in 1..=core_cnt {
|
||||||
|
|||||||
@@ -111,6 +111,24 @@ where {
|
|||||||
Ok(res)
|
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]>>
|
pub fn load<T>(&mut self, address: impl TryToUsize, size: impl TryToUsize) -> Result<Vec<&[T]>>
|
||||||
where
|
where
|
||||||
T: MemoryStorable,
|
T: MemoryStorable,
|
||||||
|
|||||||
@@ -67,14 +67,14 @@ impl From<Instructions> for CoreInstruction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Executable {
|
pub struct Executable<'a> {
|
||||||
cpu: CPU,
|
cpu: CPU<'a>,
|
||||||
core_instructions: Vec<CoreInstruction>,
|
core_instructions: Vec<CoreInstruction>,
|
||||||
send_recv : SendRecv,
|
send_recv : SendRecv,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Executable {
|
impl<'a> Executable<'a> {
|
||||||
pub fn new(cpu: CPU, core_instructions: Vec<CoreInstruction>) -> Self {
|
pub fn new(cpu: CPU<'a>, core_instructions: Vec<CoreInstruction>) -> Executable<'a> {
|
||||||
let num_core = cpu.num_core();
|
let num_core = cpu.num_core();
|
||||||
let send_recv = SendRecv::new(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)");
|
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 {
|
let Self {
|
||||||
cpu,
|
cpu ,
|
||||||
core_instructions,
|
core_instructions,
|
||||||
send_recv
|
send_recv
|
||||||
} = self;
|
} = self;
|
||||||
let mut cpu_progressed = 0;
|
let mut cpu_progressed = 0;
|
||||||
let max_core = cpu.num_core();
|
let max_core = cpu.num_core();
|
||||||
let mut index_unit = 0;
|
let mut index_unit = 0;
|
||||||
@@ -124,11 +126,11 @@ impl Executable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cpu(&self) -> &CPU {
|
pub fn cpu(&self) -> &CPU<'a> {
|
||||||
&self.cpu
|
&self.cpu
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cpu_mut(&mut self) -> &mut CPU {
|
pub fn cpu_mut(&mut self) -> &mut CPU<'a> {
|
||||||
&mut self.cpu
|
&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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -41,14 +41,16 @@ impl SendRecv {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_send_recv(
|
pub fn handle_send_recv<'a, 'b >(
|
||||||
cpu: &mut CPU,
|
cpu: &'b mut CPU<'a>,
|
||||||
core_instructions: &mut [CoreInstruction],
|
core_instructions: & mut [CoreInstruction],
|
||||||
send_recv: &mut SendRecv,
|
send_recv: & mut SendRecv,
|
||||||
core_result: InstructionStatus,
|
core_result: InstructionStatus,
|
||||||
) -> bool {
|
) -> bool
|
||||||
let transfer_memory = |cpu: &mut CPU,
|
where 'a : 'b
|
||||||
core_instructions: &mut [CoreInstruction],
|
{
|
||||||
|
let transfer_memory = |cpu: &'b mut CPU<'a>,
|
||||||
|
core_instructions: & mut [CoreInstruction],
|
||||||
sender: Option<SendRecvInfo>,
|
sender: Option<SendRecvInfo>,
|
||||||
receiver: Option<SendRecvInfo>| {
|
receiver: Option<SendRecvInfo>| {
|
||||||
if let Some(sender) = sender
|
if let Some(sender) = sender
|
||||||
@@ -117,7 +119,7 @@ pub fn handle_send_recv(
|
|||||||
send_recv.sending[sender] = None;
|
send_recv.sending[sender] = None;
|
||||||
send_recv.receiving[receiver] = None;
|
send_recv.receiving[receiver] = None;
|
||||||
}
|
}
|
||||||
return transfered;
|
transfered
|
||||||
}
|
}
|
||||||
InstructionStatus::Reciving(instruction_data) => {
|
InstructionStatus::Reciving(instruction_data) => {
|
||||||
let (core_idx, imm_core) = instruction_data.get_core_immcore();
|
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.sending[sender] = None;
|
||||||
send_recv.receiving[receiver] = None;
|
send_recv.receiving[receiver] = None;
|
||||||
}
|
}
|
||||||
return transfered;
|
transfered
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user