pub mod random;
pub mod random_priority;
pub mod islip;
use crate::Plugs;
use crate::config_parser::ConfigurationValue;
use ::rand::rngs::StdRng;
use random::RandomAllocator;
use random_priority::RandomPriorityAllocator;
use islip::ISLIPAllocator;
#[derive(Clone)]
pub struct VCARequest
{
pub entry_port: usize,
pub entry_vc: usize,
pub requested_port: usize,
pub requested_vc: usize,
pub label: i32,
}
impl VCARequest
{
pub fn to_allocator_request(&self, num_vcs: usize)->Request
{
Request::new(
self.entry_port*num_vcs+self.entry_vc,
self.requested_port*num_vcs+self.requested_vc,
if self.label<0 {None} else { Some(self.label as usize) },
)
}
}
#[derive(Clone)]
pub struct Request {
pub client: usize,
pub resource: usize,
pub priority: Option<usize>,
}
impl Request {
pub fn new(client: usize, resource: usize, priority: Option<usize>) -> Request { Self { client, resource, priority } }
pub fn to_port_request(&self, num_vcs: usize)->VCARequest
{
VCARequest{
entry_port: self.client/num_vcs,
entry_vc: self.client%num_vcs,
requested_port: self.resource/num_vcs,
requested_vc: self.resource%num_vcs,
label: if self.priority.is_none() {0} else {self.priority.unwrap() as i32},
}
}
}
#[derive(Default)]
pub struct GrantedRequests {
granted_requests: Vec<Request>,
}
impl GrantedRequests {
fn add_granted_request(&mut self, request: Request) {
self.granted_requests.push(request);
}
}
impl IntoIterator for GrantedRequests {
type Item = Request;
type IntoIter = <Vec<Request> as IntoIterator>::IntoIter;
fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
self.granted_requests.into_iter()
}
}
pub trait Allocator {
fn add_request(&mut self, request: Request);
fn perform_allocation(&mut self, rng : &mut StdRng) -> GrantedRequests;
fn support_intransit_priority(&self) -> bool;
}
#[non_exhaustive]
pub struct AllocatorBuilderArgument<'a>
{
pub cv : &'a ConfigurationValue,
pub num_resources : usize,
pub num_clients : usize,
pub plugs : &'a Plugs,
pub rng : &'a mut StdRng,
}
pub fn new_allocator(arg:AllocatorBuilderArgument) -> Box<dyn Allocator>
{
if let &ConfigurationValue::Object(ref cv_name, ref _cv_pairs)=arg.cv
{
if let Some(builder) = arg.plugs.allocators.get(cv_name) {
return builder(arg)
};
match cv_name.as_ref()
{
"Random" => Box::new(RandomAllocator::new(arg)),
"RandomWithPriority" => Box::new(RandomPriorityAllocator::new(arg)),
"Islip" | "iSLIP" =>
{
let mut cv = arg.cv.clone();
cv.rename("ISLIP".into());
let alias = AllocatorBuilderArgument{cv:&cv,..arg};
Box::new(ISLIPAllocator::new(alias))
}
"ISLIP" => Box::new(ISLIPAllocator::new(arg)),
_ => panic!("Unknown allocator: {}", cv_name),
}
}
else
{
panic!("Trying to create an Allocator from a non-Object");
}
}