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}