system_rust/
out_port.rs

1use crate::logic::LogicValue;
2use crate::resolved_signal::{ResolvedSignal, ResolvedSignalArr};
3use crate::signal::{Signal, SignalArr};
4use std::array;
5use std::fmt::Display;
6use std::ops::{Index, IndexMut};
7use std::random::random;
8use std::sync::{Arc, RwLock};
9
10pub(crate) enum WriteableSignal {
11    Signal(Signal),
12    ResolvedSignal(ResolvedSignal),
13}
14
15pub trait PortOut: Send + Sync + 'static
16where
17    LogicValue: Copy + PartialEq + Send + Sync + Display + 'static,
18{
19    fn write(&self, new_value: LogicValue);
20    fn attach(&mut self, signal: Signal);
21    fn attach_resolved(&mut self, signal: ResolvedSignal);
22}
23
24pub(crate) struct OutputPort {
25    pub signals: Vec<WriteableSignal>,
26    id: u128,
27}
28
29impl OutputPort {
30    fn new() -> Self {
31        OutputPort {
32            signals: Vec::new(),
33            id: random(),
34        }
35    }
36}
37
38impl PortOut for OutputPort {
39    fn write(&self, new_value: LogicValue) {
40        self.signals
41            .iter()
42            .for_each(|writeable_signal| match writeable_signal {
43                WriteableSignal::Signal(signal) => signal.write(new_value),
44                WriteableSignal::ResolvedSignal(signal) => signal.write(new_value, self.id),
45            });
46    }
47
48    fn attach(&mut self, signal: Signal) {
49        self.signals.push(WriteableSignal::Signal(signal));
50    }
51
52    fn attach_resolved(&mut self, signal: ResolvedSignal) {
53        self.signals.push(WriteableSignal::ResolvedSignal(signal));
54    }
55}
56
57/// A type defining an interface for modules which can be connected to signals
58/// and is used by compute modules to write data from the attached signals.
59#[derive(Clone)]
60pub struct SROut
61where
62    LogicValue: Copy + PartialEq + Send + Sync + Display + 'static,
63{
64    port: Arc<RwLock<dyn PortOut>>,
65}
66
67impl SROut
68where
69    LogicValue: Copy + PartialEq + Send + Sync + Display + 'static,
70{
71    pub fn new() -> Self {
72        SROut {
73            port: Arc::new(RwLock::new(OutputPort::new())),
74        }
75    }
76
77    pub fn write(&self, new_value: LogicValue) {
78        self.port.write().unwrap().write(new_value);
79    }
80
81    pub fn attach(&mut self, signal: &Signal) {
82        self.port.write().unwrap().attach(signal.clone());
83    }
84
85    pub fn set_to(&mut self, other: &SROut) {
86        self.port = other.port.clone();
87    }
88}
89
90impl SROut {
91    pub fn attach_resolved(&mut self, signal: &ResolvedSignal) {
92        self.port.write().unwrap().attach_resolved(signal.clone());
93    }
94}
95
96/// A wrapper for an array of SROut of fixed size, implementing some convenience features.
97#[derive(Clone)]
98pub struct SROutArr<const N: usize>
99where
100    LogicValue: Copy + PartialEq + Send + Sync + Display + 'static,
101{
102    ports: [SROut; N],
103}
104
105impl<const N: usize> SROutArr<N>
106where
107    LogicValue: Copy + PartialEq + Send + Sync + Display + 'static,
108{
109    pub fn new() -> Self {
110        SROutArr {
111            ports: array::from_fn(|_| SROut::new()),
112        }
113    }
114
115    pub fn write(&self, new_value: [LogicValue; N]) {
116        for i in 0..N {
117            self.ports[i].write(new_value[i])
118        }
119    }
120
121    pub fn attach(&mut self, signals: &SignalArr<N>) {
122        for i in 0..N {
123            self.ports[i].attach(&signals[i])
124        }
125    }
126
127    pub fn set_to(&mut self, other: &SROutArr<N>) {
128        for i in 0..N {
129            self.ports[i].set_to(&other.ports[i])
130        }
131    }
132}
133
134impl<const N: usize> SROutArr<N> {
135    pub fn attach_resolved(&mut self, signals: &ResolvedSignalArr<N>) {
136        for i in 0..N {
137            self.ports[i].attach_resolved(&signals[i])
138        }
139    }
140}
141
142impl<const N: usize> Index<usize> for SROutArr<N>
143where
144    LogicValue: Copy + PartialEq + Send + Sync + Display + 'static,
145{
146    type Output = SROut;
147
148    fn index(&self, index: usize) -> &Self::Output {
149        &self.ports[index]
150    }
151}
152
153impl<const N: usize> IndexMut<usize> for SROutArr<N>
154where
155    LogicValue: Copy + PartialEq + Send + Sync + Display + 'static,
156{
157    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
158        &mut self.ports[index]
159    }
160}