use crate::config_parser::ConfigurationValue;
use crate::routing::CandidateEgress;
use crate::router::Router;
use crate::topology::{Topology,Location};
use crate::Plugs;
use std::cell::{RefCell};
use ::rand::{Rng,StdRng};
pub struct RequestInfo<'a>
{
pub target_router_index: usize,
pub entry_port: usize,
pub entry_virtual_channel: usize,
pub performed_hops: usize,
pub server_ports: Option<&'a Vec<usize>>,
pub port_average_neighbour_queue_length: Option<&'a Vec<f32>>,
pub port_last_transmission: Option<&'a Vec<usize>>,
pub port_occupied_output_space: Option<&'a Vec<usize>>,
pub port_available_output_space: Option<&'a Vec<usize>>,
pub virtual_channel_occupied_output_space: Option<&'a Vec<Vec<usize>>>,
pub virtual_channel_available_output_space: Option<&'a Vec<Vec<usize>>>,
pub time_at_front: Option<usize>,
pub current_cycle: usize,
}
pub trait VirtualChannelPolicy
{
fn filter(&self, candidates:Vec<CandidateEgress>, router:&dyn Router, info: &RequestInfo, topology:&dyn Topology, rng: &RefCell<StdRng>) -> Vec<CandidateEgress>;
fn need_server_ports(&self)->bool;
fn need_port_average_queue_length(&self)->bool;
fn need_port_last_transmission(&self)->bool;
}
#[non_exhaustive]
#[derive(Debug)]
pub struct VCPolicyBuilderArgument<'a>
{
pub cv: &'a ConfigurationValue,
pub plugs: &'a Plugs,
}
pub fn new_virtual_channel_policy(arg:VCPolicyBuilderArgument) -> Box<dyn VirtualChannelPolicy>
{
if let &ConfigurationValue::Object(ref cv_name, ref _cv_pairs)=arg.cv
{
match arg.plugs.policies.get(cv_name)
{
Some(builder) => return builder(arg),
_ => (),
};
match cv_name.as_ref()
{
"Random" => Box::new(Random::new(arg)),
"Shortest" => Box::new(Shortest::new(arg)),
"Hops" => Box::new(Hops::new(arg)),
"EnforceFlowControl" => Box::new(EnforceFlowControl::new(arg)),
"WideHops" => Box::new(WideHops::new(arg)),
"LowestSinghWeight" => Box::new(LowestSinghWeight::new(arg)),
"LowestLabel" => Box::new(LowestLabel::new(arg)),
"LabelSaturate" => Box::new(LabelSaturate::new(arg)),
"LabelTransform" => Box::new(LabelTransform::new(arg)),
"OccupancyFunction" => Box::new(OccupancyFunction::new(arg)),
"NegateLabel" => Box::new(NegateLabel::new(arg)),
"VecLabel" => Box::new(VecLabel::new(arg)),
_ => panic!("Unknown traffic {}",cv_name),
}
}
else
{
panic!("Trying to create a traffic from a non-Object");
}
}
#[derive(Debug)]
pub struct Random{}
impl VirtualChannelPolicy for Random
{
fn filter(&self, candidates:Vec<CandidateEgress>, _router:&dyn Router, _info: &RequestInfo, _topology:&dyn Topology, rng: &RefCell<StdRng>) -> Vec<CandidateEgress>
{
vec![candidates[rng.borrow_mut().gen_range(0,candidates.len())].clone()]
}
fn need_server_ports(&self)->bool
{
false
}
fn need_port_average_queue_length(&self)->bool
{
false
}
fn need_port_last_transmission(&self)->bool
{
false
}
}
impl Random
{
pub fn new(_arg:VCPolicyBuilderArgument) -> Random
{
Random{}
}
}
#[derive(Debug)]
pub struct Shortest{}
impl VirtualChannelPolicy for Shortest
{
fn filter(&self, candidates:Vec<CandidateEgress>, router:&dyn Router, _info: &RequestInfo, _topology:&dyn Topology, _rng: &RefCell<StdRng>) -> Vec<CandidateEgress>
{
let mut best=vec![];
let mut best_credits=0;
for i in 0..candidates.len()
{
let CandidateEgress{port:p,virtual_channel:vc,..}=candidates[i];
let next_credits=router.get_status_at_emisor(p).expect("This router does not have transmission status").known_available_space_for_virtual_channel(vc).expect("remote available space is not known");
if next_credits>best_credits
{
best_credits=next_credits;
best=vec![candidates[i].clone()];
}
else if next_credits==best_credits
{
best.push(candidates[i].clone());
}
}
best
}
fn need_server_ports(&self)->bool
{
false
}
fn need_port_average_queue_length(&self)->bool
{
false
}
fn need_port_last_transmission(&self)->bool
{
false
}
}
impl Shortest
{
pub fn new(_arg:VCPolicyBuilderArgument) -> Shortest
{
Shortest{}
}
}
#[derive(Debug)]
pub struct Hops{}
impl VirtualChannelPolicy for Hops
{
fn filter(&self, candidates:Vec<CandidateEgress>, _router:&dyn Router, info: &RequestInfo, _topology:&dyn Topology, _rng: &RefCell<StdRng>) -> Vec<CandidateEgress>
{
let server_ports=info.server_ports.expect("server_ports have not been computed for policy Hops");
let filtered=candidates.into_iter().filter(|&CandidateEgress{port,virtual_channel,label:_label,estimated_remaining_hops:_,..}|virtual_channel==info.performed_hops|| server_ports.contains(&port)).collect::<Vec<_>>();
filtered
}
fn need_server_ports(&self)->bool
{
true
}
fn need_port_average_queue_length(&self)->bool
{
false
}
fn need_port_last_transmission(&self)->bool
{
false
}
}
impl Hops
{
pub fn new(_arg:VCPolicyBuilderArgument) -> Hops
{
Hops{}
}
}
#[derive(Debug)]
pub struct EnforceFlowControl{}
impl VirtualChannelPolicy for EnforceFlowControl
{
fn filter(&self, candidates:Vec<CandidateEgress>, _router:&dyn Router, _info: &RequestInfo, _topology:&dyn Topology, _rng: &RefCell<StdRng>) -> Vec<CandidateEgress>
{
let filtered=candidates.into_iter().filter(|candidate|candidate.router_allows.unwrap_or(true)).collect::<Vec<_>>();
filtered
}
fn need_server_ports(&self)->bool
{
false
}
fn need_port_average_queue_length(&self)->bool
{
false
}
fn need_port_last_transmission(&self)->bool
{
false
}
}
impl EnforceFlowControl
{
pub fn new(_arg:VCPolicyBuilderArgument) -> EnforceFlowControl
{
EnforceFlowControl{}
}
}
#[derive(Debug)]
pub struct WideHops{
width:usize,
}
impl VirtualChannelPolicy for WideHops
{
fn filter(&self, candidates:Vec<CandidateEgress>, _router:&dyn Router, info: &RequestInfo, _topology:&dyn Topology, _rng: &RefCell<StdRng>) -> Vec<CandidateEgress>
{
let server_ports=info.server_ports.expect("server_ports have not been computed for policy WideHops");
let lower_limit = self.width*info.performed_hops;
let upper_limit = self.width*(info.performed_hops+1);
let filtered=candidates.into_iter().filter(
|&CandidateEgress{port,virtual_channel,label:_,estimated_remaining_hops:_,..}| (lower_limit<=virtual_channel && virtual_channel<upper_limit) || server_ports.contains(&port)
).collect::<Vec<_>>();
filtered
}
fn need_server_ports(&self)->bool
{
true
}
fn need_port_average_queue_length(&self)->bool
{
false
}
fn need_port_last_transmission(&self)->bool
{
false
}
}
impl WideHops
{
pub fn new(arg:VCPolicyBuilderArgument) -> WideHops
{
let mut width=None;
if let &ConfigurationValue::Object(ref cv_name, ref cv_pairs)=arg.cv
{
if cv_name!="WideHops"
{
panic!("A WideHops must be created from a `WideHops` object not `{}`",cv_name);
}
for &(ref name,ref value) in cv_pairs
{
match AsRef::<str>::as_ref(&name)
{
"width" => match value
{
&ConfigurationValue::Number(f) => width=Some(f as usize),
_ => panic!("bad value for width"),
}
_ => panic!("Nothing to do with field {} in WideHops",name),
}
}
}
else
{
panic!("Trying to create a WideHops from a non-Object");
}
let width=width.expect("There were no width");
WideHops{
width
}
}
}
#[derive(Debug)]
pub struct LowestSinghWeight
{
extra_congestion: usize,
extra_distance: usize,
aggregate_buffers: bool,
use_internal_space: bool,
}
impl VirtualChannelPolicy for LowestSinghWeight
{
fn filter(&self, candidates:Vec<CandidateEgress>, router:&dyn Router, info: &RequestInfo, topology:&dyn Topology, _rng: &RefCell<StdRng>) -> Vec<CandidateEgress>
{
let port_average_neighbour_queue_length=info.port_average_neighbour_queue_length.expect("port_average_neighbour_queue_length have not been computed for policy LowestSinghWeight");
let dist=topology.distance(router.get_index().expect("we need routers with index"),info.target_router_index);
if dist==0
{
candidates
}
else
{
let mut best=vec![];
let mut best_weight=::std::f32::MAX;
for candidate in candidates
{
let CandidateEgress{port:p,virtual_channel:vc, ..} = candidate;
let next_consumed_credits:f32=(self.extra_congestion as f32)+if self.aggregate_buffers
{
if self.use_internal_space
{
let port_occupied_output_space=info.port_occupied_output_space.expect("port_occupied_output_space have not been computed for policy LowestSinghWeight");
port_occupied_output_space[p] as f32
}
else
{
port_average_neighbour_queue_length[p]
}
}
else
{
if self.use_internal_space
{
unimplemented!()
}
else
{
let next_credits=router.get_status_at_emisor(p).expect("This router does not have transmission status").known_available_space_for_virtual_channel(vc).expect("remote available space is not known");
(router.get_maximum_credits_towards(p,vc).expect("we need routers with maximum credits") - next_credits) as f32
}
};
let next_router=if let (Location::RouterPort{router_index, router_port:_},_link_class)=topology.neighbour(router.get_index().expect("we need routers with index"),p)
{
router_index
}
else
{
panic!("We trying to go to the server when we are at distance {} greater than 0.",dist);
};
let distance=self.extra_distance + 1+topology.distance(next_router,info.target_router_index);
let next_weight= next_consumed_credits * (distance as f32);
if next_weight<best_weight
{
best_weight=next_weight;
best=vec![candidate];
}
else if next_weight==best_weight
{
best.push(candidate);
}
}
best
}
}
fn need_server_ports(&self)->bool
{
false
}
fn need_port_average_queue_length(&self)->bool
{
true
}
fn need_port_last_transmission(&self)->bool
{
false
}
}
impl LowestSinghWeight
{
pub fn new(arg:VCPolicyBuilderArgument) -> LowestSinghWeight
{
let mut extra_congestion=None;
let mut extra_distance=None;
let mut aggregate_buffers=false;
let mut use_internal_space=false;
if let &ConfigurationValue::Object(ref cv_name, ref cv_pairs)=arg.cv
{
if cv_name!="LowestSinghWeight"
{
panic!("A LowestSinghWeight must be created from a `LowestSinghWeight` object not `{}`",cv_name);
}
for &(ref name,ref value) in cv_pairs
{
match AsRef::<str>::as_ref(&name)
{
"extra_congestion" => match value
{
&ConfigurationValue::Number(f) => extra_congestion=Some(f as usize),
_ => panic!("bad value for extra_congestion"),
}
"extra_distance" => match value
{
&ConfigurationValue::Number(f) => extra_distance=Some(f as usize),
_ => panic!("bad value for extra_distance"),
}
"aggregate_buffers" => match value
{
&ConfigurationValue::True => aggregate_buffers=true,
&ConfigurationValue::False => aggregate_buffers=false,
_ => panic!("bad value for aggregate_buffers"),
}
"use_internal_space" => match value
{
&ConfigurationValue::True => use_internal_space=true,
&ConfigurationValue::False => use_internal_space=false,
_ => panic!("bad value for use_internal_space"),
}
_ => panic!("Nothing to do with field {} in LowestSinghWeight",name),
}
}
}
else
{
panic!("Trying to create a LowestSinghWeight from a non-Object");
}
let extra_congestion=extra_congestion.unwrap_or(0);
let extra_distance=extra_distance.unwrap_or(0);
LowestSinghWeight{
extra_congestion,
extra_distance,
aggregate_buffers,
use_internal_space,
}
}
}
#[derive(Debug)]
pub struct LowestLabel{}
impl VirtualChannelPolicy for LowestLabel
{
fn filter(&self, candidates:Vec<CandidateEgress>, _router:&dyn Router, _info: &RequestInfo, _topology:&dyn Topology, _rng: &RefCell<StdRng>) -> Vec<CandidateEgress>
{
let mut best=vec![];
let mut best_label=<i32>::max_value();
for candidate in candidates
{
let label = candidate.label;
if label<best_label
{
best_label=label;
best=vec![candidate];
}
else if label==best_label
{
best.push(candidate);
}
}
best
}
fn need_server_ports(&self)->bool
{
false
}
fn need_port_average_queue_length(&self)->bool
{
false
}
fn need_port_last_transmission(&self)->bool
{
false
}
}
impl LowestLabel
{
pub fn new(_arg:VCPolicyBuilderArgument) -> LowestLabel
{
LowestLabel{}
}
}
#[derive(Debug)]
pub struct LabelSaturate
{
value:i32,
bottom:bool,
}
impl VirtualChannelPolicy for LabelSaturate
{
fn filter(&self, candidates:Vec<CandidateEgress>, _router:&dyn Router, _info: &RequestInfo, _topology:&dyn Topology, _rng: &RefCell<StdRng>) -> Vec<CandidateEgress>
{
if self.bottom
{
candidates.into_iter().map(
|candidate|{
let label= candidate.label;
let new_label = ::std::cmp::max(label,self.value);
CandidateEgress{label:new_label,..candidate}
}).collect::<Vec<_>>()
}
else
{
candidates.into_iter().map(
|candidate|{
let label= candidate.label;
let new_label = ::std::cmp::min(label,self.value);
CandidateEgress{label:new_label,..candidate}
}).collect::<Vec<_>>()
}
}
fn need_server_ports(&self)->bool
{
false
}
fn need_port_average_queue_length(&self)->bool
{
false
}
fn need_port_last_transmission(&self)->bool
{
false
}
}
impl LabelSaturate
{
pub fn new(arg:VCPolicyBuilderArgument) -> LabelSaturate
{
let mut xvalue=None;
let mut bottom=None;
if let &ConfigurationValue::Object(ref cv_name, ref cv_pairs)=arg.cv
{
if cv_name!="LabelSaturate"
{
panic!("A LabelSaturate must be created from a `LabelSaturate` object not `{}`",cv_name);
}
for &(ref name,ref value) in cv_pairs
{
match AsRef::<str>::as_ref(&name)
{
"value" => match value
{
&ConfigurationValue::Number(f) => xvalue=Some(f as i32),
_ => panic!("bad value for value"),
}
"bottom" => match value
{
&ConfigurationValue::True => bottom=Some(true),
&ConfigurationValue::False => bottom=Some(false),
_ => panic!("bad value for bottom"),
}
_ => panic!("Nothing to do with field {} in LabelSaturate",name),
}
}
}
else
{
panic!("Trying to create a LabelSaturate from a non-Object");
}
let value=xvalue.expect("There were no value");
let bottom=bottom.expect("There were no bottom");
LabelSaturate{
value,
bottom,
}
}
}
#[derive(Debug)]
pub struct LabelTransform
{
multiplier:i32,
summand:i32,
saturate_bottom: Option<i32>,
saturate_top: Option<i32>,
minimum: Option<i32>,
maximum: Option<i32>,
}
impl VirtualChannelPolicy for LabelTransform
{
fn filter(&self, candidates:Vec<CandidateEgress>, _router:&dyn Router, _info: &RequestInfo, _topology:&dyn Topology, _rng: &RefCell<StdRng>) -> Vec<CandidateEgress>
{
candidates.into_iter().filter_map(
|candidate|{
let mut new_label = candidate.label*self.multiplier + self.summand;
if let Some(value)=self.saturate_bottom
{
if value>new_label
{
new_label=value;
}
}
if let Some(value)=self.saturate_top
{
if value<new_label
{
new_label=value;
}
}
let mut good=true;
if let Some(value)=self.minimum
{
if value>new_label
{
good=false;
}
}
if let Some(value)=self.maximum
{
if value<new_label
{
good=false;
}
}
if good
{
Some(CandidateEgress{label:new_label,..candidate})
}
else
{
None
}
}).collect::<Vec<_>>()
}
fn need_server_ports(&self)->bool
{
false
}
fn need_port_average_queue_length(&self)->bool
{
false
}
fn need_port_last_transmission(&self)->bool
{
true
}
}
impl LabelTransform
{
pub fn new(arg:VCPolicyBuilderArgument) -> LabelTransform
{
let mut multiplier=None;
let mut summand=None;
let mut saturate_bottom=None;
let mut saturate_top=None;
let mut minimum=None;
let mut maximum=None;
if let &ConfigurationValue::Object(ref cv_name, ref cv_pairs)=arg.cv
{
if cv_name!="LabelTransform"
{
panic!("A LabelTransform must be created from a `LabelTransform` object not `{}`",cv_name);
}
for &(ref name,ref value) in cv_pairs
{
match AsRef::<str>::as_ref(&name)
{
"multiplier" => match value
{
&ConfigurationValue::Number(f) => multiplier=Some(f as i32),
_ => panic!("bad value for multiplier"),
}
"summand" => match value
{
&ConfigurationValue::Number(f) => summand=Some(f as i32),
_ => panic!("bad value for summand"),
}
"saturate_bottom" => match value
{
&ConfigurationValue::Number(f) => saturate_bottom=Some(f as i32),
_ => panic!("bad value for saturate_bottom"),
}
"saturate_top" => match value
{
&ConfigurationValue::Number(f) => saturate_top=Some(f as i32),
_ => panic!("bad value for saturate_top"),
}
"minimum" => match value
{
&ConfigurationValue::Number(f) => minimum=Some(f as i32),
_ => panic!("bad value for minimum"),
}
"maximum" => match value
{
&ConfigurationValue::Number(f) => maximum=Some(f as i32),
_ => panic!("bad value for maximum"),
}
_ => panic!("Nothing to do with field {} in LabelTransform",name),
}
}
}
else
{
panic!("Trying to create a LabelTransform from a non-Object");
}
let multiplier=multiplier.expect("There were no multiplier");
let summand=summand.expect("There were no summand");
LabelTransform{
multiplier,
summand,
saturate_bottom,
saturate_top,
minimum,
maximum,
}
}
}
#[derive(Debug)]
pub struct OccupancyFunction
{
label_coefficient: i32,
occupancy_coefficient: i32,
product_coefficient: i32,
constant_coefficient: i32,
use_internal_space: bool,
use_neighbour_space: bool,
aggregate: bool,
}
impl VirtualChannelPolicy for OccupancyFunction
{
fn filter(&self, candidates:Vec<CandidateEgress>, router:&dyn Router, info: &RequestInfo, topology:&dyn Topology, _rng: &RefCell<StdRng>) -> Vec<CandidateEgress>
{
let dist=topology.distance(router.get_index().expect("we need routers with index"),info.target_router_index);
if dist==0
{
candidates
}
else
{
candidates.into_iter().filter_map(
|candidate|{
let CandidateEgress{port,virtual_channel,label,..} = candidate;
let q=if self.use_internal_space
{
if self.aggregate
{
let port_occupied_output_space=info.port_occupied_output_space.expect("port_occupied_output_space have not been computed for policy OccupancyFunction");
port_occupied_output_space[port] as i32
}
else
{
let virtual_channel_occupied_output_space=info.virtual_channel_occupied_output_space.expect("virtual_channel_occupied_output_space have not been computed for OccupancyFunction");
virtual_channel_occupied_output_space[port][virtual_channel] as i32
}
}
else {0} + if self.use_neighbour_space
{
if self.aggregate
{
let status=router.get_status_at_emisor(port).expect("This router does not have transmission status");
(0..status.num_virtual_channels()).map(|c|router.get_maximum_credits_towards(port,c).expect("we need routers with maximum credits") as i32 - status.known_available_space_for_virtual_channel(c).expect("remote available space is not known.") as i32).sum()
}
else
{
let status=router.get_status_at_emisor(port).expect("This router does not have transmission status");
router.get_maximum_credits_towards(port,virtual_channel).expect("we need routers with maximum credits") as i32 - status.known_available_space_for_virtual_channel(virtual_channel).expect("remote available space is not known.") as i32
}
}
else {0};
let new_label = self.label_coefficient*label + self.occupancy_coefficient*q + self.product_coefficient*label*q + self.constant_coefficient;
Some(CandidateEgress{label:new_label,..candidate})
}).collect::<Vec<_>>()
}
}
fn need_server_ports(&self)->bool
{
false
}
fn need_port_average_queue_length(&self)->bool
{
false
}
fn need_port_last_transmission(&self)->bool
{
false
}
}
impl OccupancyFunction
{
pub fn new(arg:VCPolicyBuilderArgument) -> OccupancyFunction
{
let mut label_coefficient=None;
let mut occupancy_coefficient=None;
let mut product_coefficient=None;
let mut constant_coefficient=None;
let mut use_internal_space=false;
let mut use_neighbour_space=false;
let mut aggregate=true;
if let &ConfigurationValue::Object(ref cv_name, ref cv_pairs)=arg.cv
{
if cv_name!="OccupancyFunction"
{
panic!("A OccupancyFunction must be created from a `OccupancyFunction` object not `{}`",cv_name);
}
for &(ref name,ref value) in cv_pairs
{
match AsRef::<str>::as_ref(&name)
{
"label_coefficient" => match value
{
&ConfigurationValue::Number(f) => label_coefficient=Some(f as i32),
_ => panic!("bad value for label_coefficient"),
}
"occupancy_coefficient" => match value
{
&ConfigurationValue::Number(f) => occupancy_coefficient=Some(f as i32),
_ => panic!("bad value for occupancy_coefficient"),
}
"product_coefficient" => match value
{
&ConfigurationValue::Number(f) => product_coefficient=Some(f as i32),
_ => panic!("bad value for product_coefficient"),
}
"constant_coefficient" => match value
{
&ConfigurationValue::Number(f) => constant_coefficient=Some(f as i32),
_ => panic!("bad value for constant_coefficient"),
}
"use_neighbour_space" => match value
{
&ConfigurationValue::True => use_neighbour_space=true,
&ConfigurationValue::False => use_neighbour_space=false,
_ => panic!("bad value for use_neighbour_space"),
}
"use_internal_space" => match value
{
&ConfigurationValue::True => use_internal_space=true,
&ConfigurationValue::False => use_internal_space=false,
_ => panic!("bad value for use_internal_space"),
}
"aggregate" => match value
{
&ConfigurationValue::True => aggregate=true,
&ConfigurationValue::False => aggregate=false,
_ => panic!("bad value for aggregate"),
}
_ => panic!("Nothing to do with field {} in OccupancyFunction",name),
}
}
}
else
{
panic!("Trying to create a OccupancyFunction from a non-Object");
}
let label_coefficient=label_coefficient.expect("There were no multiplier");
let occupancy_coefficient=occupancy_coefficient.expect("There were no multiplier");
let product_coefficient=product_coefficient.expect("There were no multiplier");
let constant_coefficient=constant_coefficient.expect("There were no multiplier");
OccupancyFunction{
label_coefficient,
occupancy_coefficient,
product_coefficient,
constant_coefficient,
use_internal_space,
use_neighbour_space,
aggregate,
}
}
}
#[derive(Debug)]
pub struct NegateLabel
{
}
impl VirtualChannelPolicy for NegateLabel
{
fn filter(&self, candidates:Vec<CandidateEgress>, _router:&dyn Router, _info: &RequestInfo, _topology:&dyn Topology, _rng: &RefCell<StdRng>) -> Vec<CandidateEgress>
{
candidates.into_iter().filter_map(
|candidate|Some(CandidateEgress{label:-candidate.label,..candidate})
).collect::<Vec<_>>()
}
fn need_server_ports(&self)->bool
{
false
}
fn need_port_average_queue_length(&self)->bool
{
false
}
fn need_port_last_transmission(&self)->bool
{
false
}
}
impl NegateLabel
{
pub fn new(arg:VCPolicyBuilderArgument) -> NegateLabel
{
if let &ConfigurationValue::Object(ref cv_name, ref cv_pairs)=arg.cv
{
if cv_name!="NegateLabel"
{
panic!("A NegateLabel must be created from a `NegateLabel` object not `{}`",cv_name);
}
for &(ref name,ref _value) in cv_pairs
{
match AsRef::<str>::as_ref(&name)
{
_ => panic!("Nothing to do with field {} in NegateLabel",name),
}
}
}
else
{
panic!("Trying to create a NegateLabel from a non-Object");
}
NegateLabel{}
}
}
#[derive(Debug)]
pub struct VecLabel
{
label_vector: Vec<i32>,
}
impl VirtualChannelPolicy for VecLabel
{
fn filter(&self, candidates:Vec<CandidateEgress>, router:&dyn Router, info: &RequestInfo, topology:&dyn Topology, _rng: &RefCell<StdRng>) -> Vec<CandidateEgress>
{
let dist=topology.distance(router.get_index().expect("we need routers with index"),info.target_router_index);
if dist==0
{
candidates
}
else
{
candidates.into_iter().filter_map(
|candidate|{
let label = candidate.label;
if label<0 || label>=self.label_vector.len() as i32
{
panic!("label={} is out of range 0..{}",label,self.label_vector.len());
}
let new_label = self.label_vector[label as usize];
Some(CandidateEgress{label:new_label,..candidate})
}).collect::<Vec<_>>()
}
}
fn need_server_ports(&self)->bool
{
false
}
fn need_port_average_queue_length(&self)->bool
{
false
}
fn need_port_last_transmission(&self)->bool
{
false
}
}
impl VecLabel
{
pub fn new(arg:VCPolicyBuilderArgument) -> VecLabel
{
let mut label_vector=None;
if let &ConfigurationValue::Object(ref cv_name, ref cv_pairs)=arg.cv
{
if cv_name!="VecLabel"
{
panic!("A VecLabel must be created from a `VecLabel` object not `{}`",cv_name);
}
for &(ref name,ref value) in cv_pairs
{
match AsRef::<str>::as_ref(&name)
{
"label_vector" => match value
{
&ConfigurationValue::Array(ref l) => label_vector=Some(l.iter().map(|v| match v{
ConfigurationValue::Number(f) => *f as i32,
_ => panic!("bad value for label_vector"),
}).collect()),
_ => panic!("bad value for label_vector"),
}
_ => panic!("Nothing to do with field {} in VecLabel",name),
}
}
}
else
{
panic!("Trying to create a VecLabel from a non-Object");
}
let label_vector=label_vector.expect("There were no label_vector");
VecLabel{
label_vector,
}
}
}