1use std::marker::PhantomData;
2use std::sync::atomic::{AtomicUsize, Ordering};
3
4use crate::ast::{VerilogLink, VerilogLinkDetails, VerilogLiteral};
5use crate::atom::{Atom, AtomKind};
6use crate::bits::Bit;
7use crate::block::Block;
8use crate::clock::Clock;
9use crate::constraint::{Constraint, PinConstraint, SignalType};
10use crate::direction::{Direction, In, InOut, Local, Out};
11use crate::logic::{Logic, LogicJoin, LogicLink};
12use crate::probe::Probe;
13use crate::synth::{Synth, VCDValue};
14use crate::type_descriptor::TypeDescriptor;
15
16static GLOBAL_THREAD_COUNT: AtomicUsize = AtomicUsize::new(1);
17
18pub fn get_signal_id() -> usize {
19 GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::SeqCst)
20}
21
22#[derive(Clone, Debug)]
23pub struct Signal<D: Direction, T: Synth> {
24 pub next: T,
25 val: T,
26 prev: T,
27 pub changed: bool,
28 claimed: bool,
29 id: usize,
30 tristate_is_output: bool,
31 signal_is_undriven: bool,
32 constraints: Vec<PinConstraint>,
33 dir: std::marker::PhantomData<D>,
34}
35
36impl<T: Synth> Signal<In, T> {
37 pub fn join(&mut self, other: &mut Signal<Out, T>) {
38 self.next = other.val();
39 }
40 pub fn join_hdl(my_name: &str, owner_name: &str, other_name: &str) -> Vec<VerilogLink> {
41 let details = VerilogLinkDetails {
42 my_name: my_name.into(),
43 owner_name: owner_name.into(),
44 other_name: other_name.into(),
45 };
46 vec![VerilogLink::Backward(details)]
47 }
48}
49
50impl<T: Synth> Signal<Out, T> {
51 pub fn join(&mut self, other: &mut Signal<In, T>) {
52 other.next = self.val();
53 }
54 pub fn join_hdl(my_name: &str, owner_name: &str, other_name: &str) -> Vec<VerilogLink> {
55 let details = VerilogLinkDetails {
56 my_name: my_name.into(),
57 owner_name: owner_name.into(),
58 other_name: other_name.into(),
59 };
60 vec![VerilogLink::Forward(details)]
61 }
62}
63
64impl<T: Synth> LogicJoin for Signal<In, T> {
65 fn join_connect(&mut self) {
66 self.connect();
67 }
68}
69
70impl<T: Synth> LogicJoin for Signal<Out, T> {
71 fn join_connect(&mut self) {
72 self.connect();
73 }
74}
75
76impl<T: Synth> LogicJoin for Signal<InOut, T> {
77 fn join_connect(&mut self) {
78 self.connect();
79 }
80}
81
82impl<T: Synth> LogicLink for Signal<In, T> {
83 fn link(&mut self, other: &mut Self) {
84 other.next = self.val();
85 }
86 fn link_hdl(my_name: &str, owner_name: &str, other_name: &str) -> Vec<VerilogLink> {
87 let details = VerilogLinkDetails {
88 my_name: my_name.into(),
89 owner_name: owner_name.into(),
90 other_name: other_name.into(),
91 };
92 vec![VerilogLink::Forward(details)]
93 }
94 fn link_connect_source(&mut self) {
95 }
97 fn link_connect_dest(&mut self) {
98 self.connect();
99 }
100}
101
102impl<T: Synth> LogicLink for Signal<Out, T> {
103 fn link(&mut self, other: &mut Self) {
104 self.next = other.val();
105 }
106 fn link_hdl(my_name: &str, owner_name: &str, other_name: &str) -> Vec<VerilogLink> {
107 let details = VerilogLinkDetails {
108 my_name: my_name.into(),
109 owner_name: owner_name.into(),
110 other_name: other_name.into(),
111 };
112 vec![VerilogLink::Backward(details)]
113 }
114 fn link_connect_source(&mut self) {
115 self.connect();
116 }
117 fn link_connect_dest(&mut self) {}
118}
119
120impl<T: Synth> LogicLink for Signal<InOut, T> {
121 fn link(&mut self, other: &mut Self) {
122 self.tristate_is_output = other.tristate_is_output;
127 if other.tristate_is_output {
128 self.next = other.val();
129 } else {
130 other.next = self.val();
131 }
132 self.signal_is_undriven = other.signal_is_undriven;
133 }
134 fn link_hdl(my_name: &str, owner_name: &str, other_name: &str) -> Vec<VerilogLink> {
135 let details = VerilogLinkDetails {
136 my_name: my_name.into(),
137 owner_name: owner_name.into(),
138 other_name: other_name.into(),
139 };
140 vec![VerilogLink::Bidirectional(details)]
141 }
142 fn link_connect_source(&mut self) {
143 self.connect();
144 }
145 fn link_connect_dest(&mut self) {
146 self.connect();
147 }
148}
149
150impl<D: Direction, T: Synth> Signal<D, T> {
151 pub fn add_constraint(&mut self, constraint: PinConstraint) {
152 self.constraints.push(constraint);
153 }
154
155 pub fn add_location(&mut self, index: usize, location: &str) {
156 assert!(index < T::BITS);
157 self.constraints.push(PinConstraint {
158 index,
159 constraint: Constraint::Location(location.to_owned()),
160 });
161 }
162 pub fn add_signal_type(&mut self, index: usize, signal: SignalType) {
163 assert!(index < T::BITS);
164 self.constraints.push(PinConstraint {
165 index,
166 constraint: Constraint::Kind(signal),
167 });
168 }
169}
170
171impl<D: Direction, T: Synth> Atom for Signal<D, T> {
172 fn bits(&self) -> usize {
173 T::BITS
174 }
175
176 fn connected(&self) -> bool {
177 self.claimed
178 }
179
180 fn changed(&self) -> bool {
181 self.changed
182 }
183
184 fn kind(&self) -> AtomKind {
185 D::KIND
186 }
187
188 fn descriptor(&self) -> TypeDescriptor {
189 T::descriptor()
190 }
191
192 fn vcd(&self) -> VCDValue {
193 if !self.signal_is_undriven {
194 self.val.vcd()
195 } else {
196 VCDValue::Vector(vec![vcd::Value::Z; T::BITS])
197 }
198 }
199
200 fn id(&self) -> usize {
201 self.id
202 }
203
204 fn verilog(&self) -> VerilogLiteral {
205 self.val.verilog()
206 }
207
208 fn constraints(&self) -> Vec<PinConstraint> {
209 self.constraints.clone()
210 }
211}
212
213impl<D: Direction, T: Synth> Logic for Signal<D, T> {
214 fn update(&mut self) {}
215 fn connect(&mut self) {
216 self.claimed = true;
217 }
218}
219
220impl<D: Direction, T: Synth> Block for Signal<D, T> {
221 fn connect_all(&mut self) {}
222
223 fn update_all(&mut self) {
224 self.changed = self.val != self.next;
225 if self.changed {
226 self.prev = self.val;
227 self.val = self.next;
228 }
229 }
230
231 fn has_changed(&self) -> bool {
232 self.changed
233 }
234
235 fn accept(&self, name: &str, probe: &mut dyn Probe) {
236 probe.visit_atom(name, self);
237 }
238}
239
240impl Signal<In, Clock> {
241 #[inline(always)]
242 pub fn pos_edge(&self) -> bool {
243 self.changed && self.val.clk && !self.prev.clk
244 }
245 #[inline(always)]
246 pub fn neg_edge(&self) -> bool {
247 self.changed && !self.val.clk && self.prev.clk
248 }
249}
250
251impl<T: Synth> Signal<Out, T> {
252 pub fn new_with_default(init: T) -> Signal<Out, T> {
253 Self {
254 next: init,
255 val: init,
256 prev: init,
257 changed: false,
258 claimed: false,
259 id: get_signal_id(),
260 tristate_is_output: false,
261 signal_is_undriven: false,
262 constraints: vec![],
263 dir: PhantomData,
264 }
265 }
266}
267
268impl<D: Direction> Signal<D, Bit> {
269 pub fn pin_signal(location: &str, kind: SignalType) -> Signal<D, Bit> {
270 let mut ret = Signal::default();
271 ret.add_location(0, location);
272 ret.add_signal_type(0, kind);
273 ret
274 }
275}
276
277impl<D: Direction, T: Synth> Default for Signal<D, T> {
278 fn default() -> Self {
279 Self {
280 next: T::default(),
281 val: T::default(),
282 prev: T::default(),
283 changed: false,
284 claimed: false,
285 id: get_signal_id(),
286 tristate_is_output: false,
287 signal_is_undriven: false,
288 constraints: vec![],
289 dir: PhantomData,
290 }
291 }
292}
293
294impl<T: Synth> Signal<InOut, T> {
295 pub fn set_tristate_is_output(&mut self, flag: bool) {
296 if self.tristate_is_output != flag {
297 self.changed = true;
298 }
299 self.tristate_is_output = flag;
300 self.signal_is_undriven = !flag;
301 }
302 pub fn is_driving_tristate(&self) -> bool {
303 self.tristate_is_output
304 }
305 pub fn simulate_connected_tristate(&mut self, other: &mut Self) {
306 if self.is_driving_tristate() {
308 other.next = self.val();
309 self.signal_is_undriven = false;
310 other.signal_is_undriven = false;
311 } else if other.is_driving_tristate() {
312 self.next = other.val();
313 self.signal_is_undriven = false;
314 other.signal_is_undriven = false;
315 } else {
316 self.signal_is_undriven = true;
317 other.signal_is_undriven = true;
318 }
319 }
320}
321
322impl<T: Synth> Signal<InOut, T> {
323 pub fn join(&mut self, other: &mut Signal<InOut, T>) {
324 self.simulate_connected_tristate(other);
325 }
326 pub fn join_hdl(my_name: &str, owner_name: &str, other_name: &str) -> Vec<VerilogLink> {
327 let details = VerilogLinkDetails {
328 my_name: my_name.into(),
329 owner_name: owner_name.into(),
330 other_name: other_name.into(),
331 };
332 vec![VerilogLink::Bidirectional(details)]
333 }
334}
335
336impl<T: Synth> Signal<Local, T> {
344 pub fn val(&self) -> T {
345 self.next
346 }
347}
348
349impl<T: Synth> Signal<In, T> {
350 pub fn val(&self) -> T {
351 self.val
352 }
353}
354
355impl<T: Synth> Signal<Out, T> {
356 pub fn val(&self) -> T {
357 self.next
358 }
359}
360
361impl<T: Synth> Signal<InOut, T> {
362 pub fn val(&self) -> T {
363 self.val
364 }
365}