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(Source::new_and_register(
87 engine,
88 top,
89 &format!("source_{i}"),
90 Some(Box::new(FrameGen::new(
91 top,
92 u64_to_mac(neighbour_left as u64),
93 config.frame_payload_bytes,
94 config.num_send_frames,
95 ))),
96 ));
97 }
98
99 let sinks: Sinks = (0..config.ring_size)
100 .map(|i| Sink::new_and_register(engine, clock, top, &format!("sink_{i}")))
101 .collect();
102
103 (sources, sinks)
104}
105
106pub fn build_pipes(engine: &mut Engine, clock: &Clock, config: &Config) -> (Pipes, Pipes) {
107 let mut ingress_pipes = Vec::with_capacity(config.ring_size);
108 let mut ring_pipes = Vec::with_capacity(config.ring_size);
109
110 let top = engine.top();
111
112 let pipe_config = FcPipelineConfig::new(500, 500, 500);
113 for i in 0..config.ring_size {
114 ingress_pipes.push(
115 FcPipeline::new_and_register(
116 engine,
117 clock,
118 top,
119 &format!("ingress_pipe_{i}"),
120 &pipe_config,
121 )
122 .unwrap(),
123 );
124 ring_pipes.push(
125 FcPipeline::new_and_register(
126 engine,
127 clock,
128 top,
129 &format!("ring_pipe_{i}"),
130 &pipe_config,
131 )
132 .unwrap(),
133 );
134 }
135 (ingress_pipes, ring_pipes)
136}
137
138pub fn build_limiters(
139 engine: &mut Engine,
140 clock: &Clock,
141 config: &Config,
142 gbps: usize,
143) -> (Limiters, Limiters, Limiters) {
144 let limiter_gbps = rc_limiter!(clock, gbps);
145 let top = engine.top();
146 let source_limiters: Limiters = (0..config.ring_size)
147 .map(|i| {
148 Limiter::new_and_register(
149 engine,
150 clock,
151 top,
152 &format!("src_limit_{i}"),
153 limiter_gbps.clone(),
154 )
155 })
156 .collect();
157
158 let ring_limiters: Limiters = (0..config.ring_size)
159 .map(|i| {
160 Limiter::new_and_register(
161 engine,
162 clock,
163 top,
164 &format!("ring_limit_{i}"),
165 limiter_gbps.clone(),
166 )
167 })
168 .collect();
169
170 let sink_limiters: Limiters = (0..config.ring_size)
171 .map(|i| {
172 Limiter::new_and_register(
173 engine,
174 clock,
175 top,
176 &format!("sink_limit_{i}"),
177 limiter_gbps.clone(),
178 )
179 })
180 .collect();
181 (source_limiters, ring_limiters, sink_limiters)
182}