pub mod basic;
pub mod extra;
pub mod channel_operations;
pub mod updown;
pub mod polarized;
use std::cell::RefCell;
use std::fmt::Debug;
use std::convert::TryFrom;
use ::rand::{rngs::StdRng,Rng,prelude::SliceRandom};
use crate::config_parser::ConfigurationValue;
use crate::topology::cartesian::{DOR,O1TURN,ValiantDOR,OmniDimensionalDeroute, DimWAR, GENERALTURN, Valiant4Hamming};
use crate::topology::dragonfly::{PAR, Valiant4Dragonfly};
use crate::topology::{Topology,Location};
pub use crate::event::Time;
use quantifiable_derive::Quantifiable;use crate::{Plugs};
pub use crate::error::Error;
pub use self::basic::*;
pub use self::extra::*;
pub use self::channel_operations::*;
pub use self::updown::*;
pub use self::polarized::Polarized;
pub mod prelude
{
pub use super::{new_routing,Routing,RoutingInfo,RoutingNextCandidates,CandidateEgress,RoutingBuilderArgument,Error,Time};
}
#[derive(Quantifiable)]
#[derive(Debug)]
pub struct RoutingInfo
{
pub hops: usize,
pub routing_record: Option<Vec<i32>>,
pub selected_path: Option<Vec<usize>>,
pub selections: Option<Vec<i32>>,
pub visited_routers: Option<Vec<usize>>,
pub meta: Option<Vec<RefCell<RoutingInfo>>>,
pub auxiliar: RefCell<Option<Box<dyn std::any::Any>>>,
}
impl RoutingInfo
{
pub fn new() -> RoutingInfo
{
RoutingInfo{
hops: 0,
routing_record: None,
selected_path: None,
selections: None,
visited_routers: None,
meta: None,
auxiliar: RefCell::new(None),
}
}
}
#[derive(Clone,Debug,Default)]
pub struct RoutingAnnotation
{
pub(crate) values: Vec<i32>,
pub(crate) meta: Vec<Option<RoutingAnnotation>>,
}
#[derive(Clone)]
#[derive(Debug,Default)]
pub struct CandidateEgress
{
pub port: usize,
pub virtual_channel: usize,
pub label: i32,
pub estimated_remaining_hops: Option<usize>,
pub router_allows: Option<bool>,
pub annotation: Option<RoutingAnnotation>,
}
impl CandidateEgress
{
pub fn new(port:usize, virtual_channel:usize)->CandidateEgress
{
CandidateEgress{
port,
virtual_channel,
label: 0,
estimated_remaining_hops: None,
router_allows: None,
annotation: None,
}
}
}
#[derive(Clone,Debug,Default)]
pub struct RoutingNextCandidates
{
pub candidates: Vec<CandidateEgress>,
pub idempotent: bool,
}
impl From<RoutingNextCandidates> for Vec<CandidateEgress>
{
fn from(candidates: RoutingNextCandidates) -> Self
{
candidates.candidates
}
}
impl IntoIterator for RoutingNextCandidates
{
type Item = CandidateEgress;
type IntoIter = <Vec<CandidateEgress> as IntoIterator>::IntoIter;
fn into_iter(self) -> <Self as IntoIterator>::IntoIter
{
self.candidates.into_iter()
}
}
impl RoutingNextCandidates
{
pub fn len(&self)->usize
{
self.candidates.len()
}
}
pub trait Routing : Debug
{
fn next(&self, routing_info:&RoutingInfo, topology:&dyn Topology, current_router:usize, target_router:usize, target_server:Option<usize>, num_virtual_channels:usize, rng: &mut StdRng) -> Result<RoutingNextCandidates,Error>;
fn initialize_routing_info(&self, _routing_info:&RefCell<RoutingInfo>, _topology:&dyn Topology, _current_router:usize, _target_touter:usize, _target_server:Option<usize>, _rng: &mut StdRng) {}
fn update_routing_info(&self, _routing_info:&RefCell<RoutingInfo>, _topology:&dyn Topology, _current_router:usize, _current_port:usize, _target_router:usize, _target_server:Option<usize>,_rng: &mut StdRng) {}
fn initialize(&mut self, _topology:&dyn Topology, _rng: &mut StdRng) {}
fn performed_request(&self, _requested:&CandidateEgress, _routing_info:&RefCell<RoutingInfo>, _topology:&dyn Topology, _current_router:usize, _target_router:usize, _target_server:Option<usize>, _num_virtual_channels:usize, _rng:&mut StdRng) {}
fn statistics(&self,_cycle:Time) -> Option<ConfigurationValue>{ None }
fn reset_statistics(&mut self,_next_cycle:Time) {}
}
#[derive(Debug)]
pub struct RoutingBuilderArgument<'a>
{
pub cv: &'a ConfigurationValue,
pub plugs: &'a Plugs,
}
pub fn new_routing(arg: RoutingBuilderArgument) -> Box<dyn Routing>
{
if let &ConfigurationValue::Object(ref cv_name, ref _cv_pairs)=arg.cv
{
match arg.plugs.routings.get(cv_name)
{
Some(builder) => return builder(arg),
_ => (),
};
match cv_name.as_ref()
{
"DOR" => Box::new(DOR::new(arg)),
"O1TURN" => Box::new(O1TURN::new(arg)),
"GeneralTurn" => Box::new(GENERALTURN::new(arg)),
"OmniDimensionalDeroute" => Box::new(OmniDimensionalDeroute::new(arg)),
"DimWAR" => Box::new(DimWAR::new(arg)),
"Valiant4Hamming" => Box::new(Valiant4Hamming::new(arg)),
"Valiant4Dragonfly" => Box::new(Valiant4Dragonfly::new(arg)),
"PAR" => Box::new(PAR::new(arg)),
"Shortest" => Box::new(Shortest::new(arg)),
"Valiant" => Box::new(Valiant::new(arg)),
"ValiantDOR" => Box::new(ValiantDOR::new(arg)),
"Polarized" => Box::new(Polarized::new(arg)),
"Sum" => Box::new(SumRouting::new(arg)),
"Mindless" => Box::new(Mindless::new(arg)),
"WeighedShortest" => Box::new(WeighedShortest::new(arg)),
"Stubborn" => Box::new(Stubborn::new(arg)),
"UpDown" => Box::new(UpDown::new(arg)),
"UpDownStar" => Box::new(ExplicitUpDown::new(arg)),
"ChannelsPerHop" => Box::new(ChannelsPerHop::new(arg)),
"ChannelsPerHopPerLinkClass" => Box::new(ChannelsPerHopPerLinkClass::new(arg)),
"AscendantChannelsWithLinkClass" => Box::new(AscendantChannelsWithLinkClass::new(arg)),
"ChannelMap" => Box::new(ChannelMap::new(arg)),
"Dragonfly2Colors" => Box::new(crate::topology::dragonfly::Dragonfly2ColorsRouting::new(arg)),
_ => panic!("Unknown Routing {}",cv_name),
}
}
else
{
panic!("Trying to create a Routing from a non-Object");
}
}
pub trait SourceRouting
{
fn initialize(&mut self, topology:&dyn Topology, rng: &mut StdRng);
fn get_paths(&self, source:usize, target:usize) -> &Vec<Vec<usize>>;
}
pub trait InstantiableSourceRouting : SourceRouting + Debug {}
impl<R:SourceRouting + Debug> InstantiableSourceRouting for R {}
impl<R:SourceRouting+Debug> Routing for R
{
fn next(&self, routing_info:&RoutingInfo, topology:&dyn Topology, current_router:usize, target_router: usize, target_server:Option<usize>, num_virtual_channels:usize, _rng: &mut StdRng) -> Result<RoutingNextCandidates,Error>
{
let distance=topology.distance(current_router,target_router);
if distance==0
{
let target_server = target_server.expect("target server was not given.");
for i in 0..topology.ports(current_router)
{
if let (Location::ServerPort(server),_link_class)=topology.neighbour(current_router,i)
{
if server==target_server
{
return Ok(RoutingNextCandidates{candidates:(0..num_virtual_channels).map(|vc|CandidateEgress::new(i,vc)).collect(),idempotent:true});
}
}
}
unreachable!();
}
let num_ports=topology.ports(current_router);
let mut r=Vec::with_capacity(num_ports*num_virtual_channels);
let next_router=routing_info.selected_path.as_ref().unwrap()[routing_info.hops+1];
let length =routing_info.selected_path.as_ref().unwrap().len() - 1; let remain = length - routing_info.hops;
for i in 0..num_ports
{
if let (Location::RouterPort{router_index,router_port:_},_link_class)=topology.neighbour(current_router,i)
{
if router_index==next_router
{
r.extend((0..num_virtual_channels).map(|vc|{
let mut egress = CandidateEgress::new(i,vc);
egress.estimated_remaining_hops = Some(remain);
egress
}));
}
}
}
Ok(RoutingNextCandidates{candidates:r,idempotent:true})
}
fn initialize_routing_info(&self, routing_info:&RefCell<RoutingInfo>, _topology:&dyn Topology, current_router:usize, target_router:usize, _target_server:Option<usize>, rng: &mut StdRng)
{
if current_router!=target_router
{
let path_collection = self.get_paths(current_router,target_router);
if path_collection.is_empty()
{
panic!("No path found from router {} to router {}",current_router,target_router);
}
let r=rng.gen_range(0..path_collection.len());
routing_info.borrow_mut().selected_path=Some(path_collection[r].clone());
}
}
fn initialize(&mut self, topology:&dyn Topology, rng: &mut StdRng)
{
self.initialize(topology,rng);
}
}
#[derive(Debug)]
pub struct SourceAdaptiveRouting
{
pub routing: Box<dyn InstantiableSourceRouting>,
pub amount: usize,
}
impl Routing for SourceAdaptiveRouting
{
fn next(&self, routing_info:&RoutingInfo, topology:&dyn Topology, current_router:usize, target_router: usize, target_server:Option<usize>, num_virtual_channels:usize, _rng: &mut StdRng) -> Result<RoutingNextCandidates,Error>
{
let distance=topology.distance(current_router,target_router);
if distance==0
{
let target_server = target_server.expect("target server was not given.");
for i in 0..topology.ports(current_router)
{
if let (Location::ServerPort(server),_link_class)=topology.neighbour(current_router,i)
{
if server==target_server
{
return Ok(RoutingNextCandidates{
candidates:(0..num_virtual_channels).map(|vc|CandidateEgress::new(i,vc)).collect(),
idempotent:true
});
}
}
}
unreachable!();
}
let source_router = routing_info.visited_routers.as_ref().unwrap()[0];
let num_ports=topology.ports(current_router);
let mut r=Vec::with_capacity(num_ports*num_virtual_channels);
let selections = routing_info.selections.as_ref().unwrap().clone();
for path_index in selections
{
let path = &self.routing.get_paths(source_router,target_router)[<usize>::try_from(path_index).unwrap()];
let next_router = path[routing_info.hops+1];
let length = path.len() - 1; let remain = length - routing_info.hops;
for i in 0..num_ports
{
if let (Location::RouterPort{router_index,router_port:_},_link_class)=topology.neighbour(current_router,i)
{
if router_index==next_router
{
r.extend((0..num_virtual_channels).map(|vc|{
let mut egress = CandidateEgress::new(i,vc);
egress.estimated_remaining_hops = Some(remain);
egress
}));
}
}
}
}
Ok(RoutingNextCandidates{candidates:r,idempotent:true})
}
fn initialize_routing_info(&self, routing_info:&RefCell<RoutingInfo>, _topology:&dyn Topology, current_router:usize, target_router:usize, _target_server:Option<usize>, rng: &mut StdRng)
{
routing_info.borrow_mut().visited_routers=Some(vec![current_router]);
if current_router!=target_router
{
let path_collection = self.routing.get_paths(current_router,target_router);
if path_collection.is_empty()
{
panic!("No path found from router {} to router {}",current_router,target_router);
}
let mut selected_indices : Vec<i32> = (0i32..<i32>::try_from(path_collection.len()).unwrap()).collect();
if selected_indices.len()>self.amount
{
selected_indices.shuffle(rng);
selected_indices.resize_with(self.amount,||unreachable!());
}
routing_info.borrow_mut().selections=Some(selected_indices);
}
}
fn update_routing_info(&self, routing_info:&RefCell<RoutingInfo>, _topology:&dyn Topology, current_router:usize, _current_port:usize, target_router:usize, _target_server:Option<usize>, _rng: &mut StdRng)
{
let mut ri=routing_info.borrow_mut();
let hops = ri.hops;
if let Some(ref mut visited)=ri.visited_routers
{
let source_router = visited[0];
visited.push(current_router);
let paths = &self.routing.get_paths(source_router,target_router);
if let Some(ref mut selections)=ri.selections
{
selections.retain(|path_index|{
let path = &paths[<usize>::try_from(*path_index).unwrap()];
path[hops]==current_router
});
if selections.is_empty()
{
panic!("No selections remaining.");
}
}
}
}
fn initialize(&mut self, topology:&dyn Topology, rng: &mut StdRng)
{
self.routing.initialize(topology,rng);
}
}