gpt/
gpt.rs

1mod generator {
2    pub struct GeneratorState {
3        sigma: f64,
4        period: f64,
5        count: usize,
6    }
7
8    impl GeneratorState {
9        pub fn new(period: f64) -> Self {
10            Self {
11                sigma: 0.0,
12                period,
13                count: 0,
14            }
15        }
16    }
17
18    xdevs::component!(
19        ident = Generator,
20        input = {
21            in_stop<bool>,
22        },
23        output = {
24            out_job<usize>,
25        },
26        state = GeneratorState,
27    );
28
29    impl xdevs::Atomic for Generator {
30        fn delta_int(state: &mut Self::State) {
31            state.count += 1;
32            state.sigma = state.period;
33        }
34
35        fn lambda(state: &Self::State, output: &mut Self::Output) {
36            println!("[G] sending job {}", state.count);
37            output.out_job.add_value(state.count).unwrap();
38        }
39
40        fn ta(state: &Self::State) -> f64 {
41            state.sigma
42        }
43
44        fn delta_ext(state: &mut Self::State, e: f64, x: &Self::Input) {
45            state.sigma -= e;
46            if let Some(&stop) = x.in_stop.get_values().last() {
47                println!("[G] received stop: {}", stop);
48                if stop {
49                    state.sigma = f64::INFINITY;
50                }
51            }
52        }
53    }
54}
55
56mod processor {
57    pub struct ProcessorState {
58        sigma: f64,
59        time: f64,
60        job: Option<usize>,
61    }
62
63    impl ProcessorState {
64        pub fn new(time: f64) -> Self {
65            Self {
66                sigma: 0.0,
67                time,
68                job: None,
69            }
70        }
71    }
72
73    xdevs::component!(
74        ident = Processor,
75        input = {
76            in_job<usize, 1>
77        },
78        output = {
79            out_job<usize>
80        },
81        state = ProcessorState,
82    );
83
84    impl xdevs::Atomic for Processor {
85        fn delta_int(state: &mut Self::State) {
86            state.sigma = f64::INFINITY;
87            if let Some(job) = state.job {
88                println!("[P] processed job {}", job);
89                state.job = None;
90            }
91        }
92
93        fn lambda(state: &Self::State, output: &mut Self::Output) {
94            if let Some(job) = state.job {
95                output.out_job.add_value(job).unwrap();
96            }
97        }
98
99        fn ta(state: &Self::State) -> f64 {
100            state.sigma
101        }
102
103        fn delta_ext(state: &mut Self::State, e: f64, x: &Self::Input) {
104            state.sigma -= e;
105            if let Some(&job) = x.in_job.get_values().last() {
106                print!("[P] received job {}", job);
107                if state.job.is_none() {
108                    println!(" (idle)");
109                    state.job = Some(job);
110                    state.sigma = state.time;
111                } else {
112                    println!(" (busy)");
113                }
114            }
115        }
116    }
117}
118
119mod transducer {
120    pub struct TransducerState {
121        sigma: f64,
122        clock: f64,
123        n_generated: usize,
124        n_processed: usize,
125    }
126
127    impl TransducerState {
128        pub fn new(obs_time: f64) -> Self {
129            Self {
130                sigma: obs_time,
131                clock: 0.0,
132                n_generated: 0,
133                n_processed: 0,
134            }
135        }
136    }
137
138    xdevs::component!(
139        ident = Transducer,
140        input = {
141            in_generator<usize, 1>,
142            in_processor<usize, 1>,
143        },
144        output = {
145            out_stop<bool>
146        },
147        state = TransducerState,
148    );
149
150    impl xdevs::Atomic for Transducer {
151        fn delta_int(state: &mut Self::State) {
152            state.clock += state.sigma;
153            let (acceptance, throughput) = if state.n_processed > 0 {
154                (
155                    state.n_processed as f64 / state.n_generated as f64,
156                    state.n_processed as f64 / state.clock,
157                )
158            } else {
159                (0.0, 0.0)
160            };
161            println!(
162                "[T] acceptance: {:.2}, throughput: {:.2}",
163                acceptance, throughput
164            );
165            state.sigma = f64::INFINITY;
166        }
167
168        fn lambda(_state: &Self::State, output: &mut Self::Output) {
169            output.out_stop.add_value(true).unwrap();
170        }
171
172        fn ta(state: &Self::State) -> f64 {
173            state.sigma
174        }
175
176        fn delta_ext(state: &mut Self::State, e: f64, x: &Self::Input) {
177            state.sigma -= e;
178            state.clock += e;
179            state.n_generated += x.in_generator.get_values().len();
180            state.n_processed += x.in_processor.get_values().len();
181        }
182    }
183}
184
185xdevs::component!(
186    ident = GPT,
187    components = {
188        generator: generator::Generator,
189        processor: processor::Processor,
190        transducer: transducer::Transducer,
191    },
192    couplings = {
193        generator.out_job -> processor.in_job,
194        processor.out_job -> transducer.in_processor,
195        generator.out_job -> transducer.in_generator,
196        transducer.out_stop -> generator.in_stop,
197    }
198);
199
200xdevs::component!(
201    ident = EF,
202    input = {
203        in_processor<usize, 1>,
204    },
205    output = {
206        out_generator<usize, 1>,
207    },
208    components = {
209        generator: generator::Generator,
210        transducer: transducer::Transducer,
211    },
212    couplings = {
213        in_processor -> transducer.in_processor,
214        generator.out_job -> transducer.in_generator,
215        transducer.out_stop -> generator.in_stop,
216        generator.out_job -> out_generator,
217    }
218);
219
220xdevs::component!(
221    ident = EFP,
222    components = {
223        ef: EF,
224        processor: processor::Processor,
225    },
226    couplings = {
227        ef.out_generator -> processor.in_job,
228        processor.out_job -> ef.in_processor,
229    }
230);
231
232fn main() {
233    let period = 1.;
234    let proc_time = 1.1;
235    let obs_time = 10.;
236
237    let generator = generator::Generator::new(generator::GeneratorState::new(period));
238    let processor = processor::Processor::new(processor::ProcessorState::new(proc_time));
239    let transducer = transducer::Transducer::new(transducer::TransducerState::new(obs_time));
240
241    let ef = EF::new(generator, transducer);
242    let efp = EFP::new(ef, processor);
243
244    let mut simulator = xdevs::simulator::Simulator::new(efp);
245    simulator.simulate_rt(
246        0.0,
247        14.0,
248        xdevs::simulator::std::sleep(0.0, 1.0, None),
249        |_| {},
250    );
251}