rust_hdl_core/
signal.rs

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        // Does nothing
96    }
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 is the outer scope, other is the inner scope
123        // So if the inner scope is driven, we take it's value
124        // and mark ourselves as driven.  If the inner scope is
125        // not driven, we are not driven and we push our value
126        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        //        assert!(!(self.is_driving_tristate() & other.is_driving_tristate()));
307        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
336// For local signals only
337// There should be a write before a read
338//  (will that trigger latch detection if violated?)
339// .val() -> next
340// local signals do not generate changes.
341// Need loop detection
342
343impl<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}