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