scrambler/
lib.rs

1// Copyright (c) 2023 Graphcore Ltd. All rights reserved.
2
3//! An example component which can switch the how its inputs are connected.
4//!
5//! For latest usage run:
6//! ```bash
7//! cargo run --bin scrambler -- --help
8//! ```
9//!
10//! # Examples
11//!
12//! Get the two inputs in the same order:
13//! ```bash
14//! $ cargo run --bin scrambler
15//! Input order: 1, 2
16//! ```
17//!
18//! Switch the two inputs:
19//! ```bash
20//! $ cargo run --bin scrambler -- -s
21//! Input order: 2, 1
22//! ```
23//!
24//! # Ports
25//!
26//! This component has four ports
27//!  - Two [input port](gwr_engine::port::InPort): `rx_a`, `rx_b`
28//!  - Two [output port](gwr_engine::port::OutPort): `tx_a`, `tx_b`
29
30use std::rc::Rc;
31
32use async_trait::async_trait;
33use gwr_components::store::Store;
34use gwr_engine::engine::Engine;
35use gwr_engine::executor::Spawner;
36use gwr_engine::port::PortStateResult;
37use gwr_engine::traits::SimObject;
38use gwr_engine::types::{SimError, SimResult};
39use gwr_model_builder::{EntityDisplay, Runnable};
40use gwr_track::entity::Entity;
41
42#[derive(EntityDisplay, Runnable)]
43pub struct Scrambler<T>
44where
45    T: SimObject,
46{
47    pub entity: Rc<Entity>,
48    scramble: bool,
49    buffer_a: Rc<Store<T>>,
50    buffer_b: Rc<Store<T>>,
51}
52
53impl<T> Scrambler<T>
54where
55    T: SimObject,
56{
57    pub fn new_and_register(
58        engine: &Engine,
59        parent: &Rc<Entity>,
60        name: &str,
61        spawner: Spawner,
62        scramble: bool,
63    ) -> Result<Rc<Self>, SimError> {
64        let entity = Rc::new(Entity::new(parent, name));
65        let buffer_a = Store::new_and_register(engine, &entity, "buffer_a", spawner.clone(), 1)?;
66        let buffer_b = Store::new_and_register(engine, &entity, "buffer_b", spawner, 1)?;
67
68        let rc_self = Rc::new(Self {
69            entity: entity.clone(),
70            scramble,
71            buffer_a,
72            buffer_b,
73        });
74        engine.register(rc_self.clone());
75        Ok(rc_self)
76    }
77
78    pub fn connect_port_tx_a(&self, port_state: PortStateResult<T>) -> SimResult {
79        if self.scramble {
80            self.buffer_b.connect_port_tx(port_state)
81        } else {
82            self.buffer_a.connect_port_tx(port_state)
83        }
84    }
85
86    pub fn connect_port_tx_b(&self, port_state: PortStateResult<T>) -> SimResult {
87        if self.scramble {
88            self.buffer_a.connect_port_tx(port_state)
89        } else {
90            self.buffer_b.connect_port_tx(port_state)
91        }
92    }
93
94    pub fn port_rx_a(&self) -> PortStateResult<T> {
95        self.buffer_a.port_rx()
96    }
97
98    pub fn port_rx_b(&self) -> PortStateResult<T> {
99        self.buffer_b.port_rx()
100    }
101}