rust_hdl_core/
constant.rs

1use crate::ast::VerilogLiteral;
2use crate::atom::{Atom, AtomKind};
3use crate::bits::Bits;
4use crate::block::Block;
5use crate::constraint::PinConstraint;
6use crate::logic::Logic;
7use crate::probe::Probe;
8use crate::signal::{get_signal_id, Signal};
9use crate::sim_assert_eq;
10use crate::simulate::{Sim, Simulation};
11use crate::synth::{Synth, VCDValue};
12use crate::type_descriptor::TypeDescriptor;
13
14/// The [Constant] wrapper can hold any [Synth] type
15/// and store it in a circuit for use by the HDL kernel.
16/// This is the easiest way to compute complex constants
17/// in your RustHDL constructors, and then store the
18/// results inside the circuit for later use.  Unlike
19/// [Signal], [Constant] does not have a `.next` field,
20/// so you cannot assign to a [Constant] in the HDL
21/// kernel (blocked at compile time).  Note that [Constant]
22/// does not `impl Default`.  You must construct it
23/// with the appropriate value when the circuit is built.
24///
25/// Here is a correct usage of a [Constant]
26/// ```rust
27///  use rust_hdl_core::prelude::*;
28///
29/// #[derive(LogicBlock)]
30/// struct AddNum {
31///    pub i1: Signal<In, Bits<8>>,
32///    pub o1: Signal<Out, Bits<8>>,
33///    c1: Constant<Bits<8>>,
34/// }
35///
36/// impl Default for AddNum {
37///     fn default() -> Self {
38///          Self {
39///             i1: Default::default(),
40///             o1: Default::default(),
41///             c1: Constant::new(42.into()),
42///          }
43///     }
44/// }
45///
46/// impl Logic for AddNum {
47///      #[hdl_gen]
48///      fn update(&mut self) {
49///         // Note that `self.c1.next` does not exist...
50///         self.o1.next = self.i1.val() + self.c1.val();
51///      }
52/// }
53///
54///    let mut sim : Simulation<AddNum> = Simulation::default();
55///    sim.add_testbench(|mut ep: Sim<AddNum>| {
56///        let mut x = ep.init()?;
57///        x.i1.next = 13.into();
58///        x = ep.wait(1, x)?;
59///        sim_assert_eq!(ep, x.o1.val(), 55, x);
60///        ep.done(x)
61///    });
62///    
63///    let mut uut = AddNum::default(); uut.connect_all();
64///    sim.run(Box::new(uut), 100).unwrap();
65///```
66#[derive(Copy, Clone, Debug)]
67pub struct Constant<T: Synth> {
68    val: T,
69    id: usize,
70}
71
72impl<T: Synth> Constant<T> {
73    /// Create a new [Constant] from the given value.
74    pub fn new(val: T) -> Constant<T> {
75        Constant {
76            val,
77            id: get_signal_id(),
78        }
79    }
80    /// Retrieve the value of the constant.  Usable in HDL kernels.
81    pub fn val(&self) -> T {
82        self.val
83    }
84}
85
86impl<T: Synth> Logic for Constant<T> {
87    fn update(&mut self) {}
88
89    fn connect(&mut self) {}
90}
91
92impl<T: Synth> Atom for Constant<T> {
93    fn bits(&self) -> usize {
94        T::BITS
95    }
96
97    fn connected(&self) -> bool {
98        true
99    }
100
101    fn changed(&self) -> bool {
102        false
103    }
104
105    fn kind(&self) -> AtomKind {
106        AtomKind::Constant
107    }
108
109    fn descriptor(&self) -> TypeDescriptor {
110        T::descriptor()
111    }
112
113    fn vcd(&self) -> VCDValue {
114        self.val.vcd()
115    }
116
117    fn verilog(&self) -> VerilogLiteral {
118        self.val.verilog()
119    }
120
121    fn id(&self) -> usize {
122        self.id
123    }
124
125    fn constraints(&self) -> Vec<PinConstraint> {
126        vec![]
127    }
128}
129
130impl<T: Synth> Block for Constant<T> {
131    fn connect_all(&mut self) {}
132
133    fn update_all(&mut self) {}
134
135    fn has_changed(&self) -> bool {
136        false
137    }
138
139    fn accept(&self, name: &str, probe: &mut dyn Probe) {
140        probe.visit_atom(name, self);
141    }
142}