1use std::rc::Rc;
6
7use gwr_components::arbiter::policy::WeightedRoundRobin;
8use gwr_components::flow_controls::limiter::Limiter;
9use gwr_components::rc_limiter;
10use gwr_components::router::Route;
11use gwr_components::sink::Sink;
12use gwr_components::source::Source;
13use gwr_engine::engine::Engine;
14use gwr_engine::traits::Routable;
15use gwr_engine::types::SimError;
16use gwr_models::ethernet_frame::{EthernetFrame, u64_to_mac};
17use gwr_models::fc_pipeline::{FcPipeline, FcPipelineConfig};
18use gwr_models::ring_node::{IO_INDEX, RING_INDEX, RingConfig, RingNode};
19
20use crate::frame_gen::FrameGen;
21
22pub type Limiters = Vec<Rc<Limiter<EthernetFrame>>>;
24pub type Nodes = Vec<Rc<RingNode<EthernetFrame>>>;
25pub type Pipes = Vec<Rc<FcPipeline<EthernetFrame>>>;
26pub type Sources = Vec<Rc<Source<EthernetFrame>>>;
27pub type Sinks = Vec<Rc<Sink<EthernetFrame>>>;
28
29pub struct Config {
30 pub ring_size: usize,
31 pub ring_priority: usize,
32 pub rx_buffer_frames: usize,
33 pub tx_buffer_frames: usize,
34 pub frame_payload_bytes: usize,
35 pub num_send_frames: usize,
36}
37
38struct RoutingAlgorithm(usize);
39
40impl<T> Route<T> for RoutingAlgorithm
41where
42 T: Routable,
43{
44 fn route(&self, obj: &T) -> Result<usize, SimError> {
45 let dest = obj.destination() as usize;
48 Ok(if self.0 == dest { IO_INDEX } else { RING_INDEX })
49 }
50}
51
52pub fn build_ring_nodes(engine: &mut Engine, config: &Config) -> Nodes {
53 let spawner = engine.spawner().clone();
54 let clock = engine.default_clock().clone();
55 let limiter_128_gbps = rc_limiter!(clock.clone(), 128);
56 let ring_config = RingConfig::new(
57 config.rx_buffer_frames,
58 config.tx_buffer_frames,
59 limiter_128_gbps.clone(),
60 );
61 let top = engine.top();
62 let ring_nodes: Nodes = (0..config.ring_size)
63 .map(|i| {
64 let weights = vec![config.ring_priority, 1];
65 RingNode::new_and_register(
66 engine,
67 top,
68 format!("node{i}").as_str(),
69 spawner.clone(),
70 &ring_config,
71 Box::new(RoutingAlgorithm(i)),
72 Box::new(WeightedRoundRobin::new(weights, 2).unwrap()),
73 )
74 .unwrap()
75 })
76 .collect();
77 ring_nodes
78}
79
80pub fn build_source_sinks(engine: &mut Engine, config: &Config) -> (Sources, Sinks) {
81 let mut sources = Vec::with_capacity(config.ring_size);
82 let top = engine.top();
83
84 for i in 0..config.ring_size {
85 let neighbour_left = if i > 0 { i - 1 } else { config.ring_size - 1 };
86
87 sources.push(
88 Source::new_and_register(
89 engine,
90 top,
91 format!("source{i}").as_str(),
92 Some(Box::new(FrameGen::new(
93 top,
94 u64_to_mac(neighbour_left as u64),
95 config.frame_payload_bytes,
96 config.num_send_frames,
97 ))),
98 )
99 .unwrap(),
100 );
101 }
102
103 let sinks: Sinks = (0..config.ring_size)
104 .map(|i| Sink::new_and_register(engine, top, format!("sink{i}").as_str()).unwrap())
105 .collect();
106
107 (sources, sinks)
108}
109
110pub fn build_pipes(engine: &mut Engine, config: &Config) -> (Pipes, Pipes) {
111 let mut ingress_pipes = Vec::with_capacity(config.ring_size);
112 let mut ring_pipes = Vec::with_capacity(config.ring_size);
113
114 let clock = engine.default_clock();
115 let top = engine.top();
116 let spawner = engine.spawner();
117
118 let pipe_config = FcPipelineConfig::new(500, 500, 500);
119 for i in 0..config.ring_size {
120 ingress_pipes.push(
121 FcPipeline::new_and_register(
122 engine,
123 top,
124 format!("ingress_pipe{i}").as_str(),
125 clock.clone(),
126 spawner.clone(),
127 &pipe_config,
128 )
129 .unwrap(),
130 );
131 ring_pipes.push(
132 FcPipeline::new_and_register(
133 engine,
134 top,
135 format!("ring_pipe{i}").as_str(),
136 clock.clone(),
137 spawner.clone(),
138 &pipe_config,
139 )
140 .unwrap(),
141 );
142 }
143 (ingress_pipes, ring_pipes)
144}
145
146pub fn build_limiters(
147 engine: &mut Engine,
148 config: &Config,
149 gbps: usize,
150) -> (Limiters, Limiters, Limiters) {
151 let clock = engine.default_clock();
152 let limiter_gbps = rc_limiter!(clock, gbps);
153 let top = engine.top();
154 let source_limiters: Limiters = (0..config.ring_size)
155 .map(|i| {
156 Limiter::new_and_register(
157 engine,
158 top,
159 format!("src_limit{i}").as_str(),
160 limiter_gbps.clone(),
161 )
162 .unwrap()
163 })
164 .collect();
165
166 let ring_limiters: Limiters = (0..config.ring_size)
167 .map(|i| {
168 Limiter::new_and_register(
169 engine,
170 top,
171 format!("ring_limit{i}").as_str(),
172 limiter_gbps.clone(),
173 )
174 .unwrap()
175 })
176 .collect();
177
178 let sink_limiters: Limiters = (0..config.ring_size)
179 .map(|i| {
180 Limiter::new_and_register(
181 engine,
182 top,
183 format!("sink_limit{i}").as_str(),
184 limiter_gbps.clone(),
185 )
186 .unwrap()
187 })
188 .collect();
189 (source_limiters, ring_limiters, sink_limiters)
190}