1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use crate::ast::VerilogLiteral;
use crate::atom::{Atom, AtomKind};
use crate::bits::Bits;
use crate::block::Block;
use crate::constraint::PinConstraint;
use crate::logic::Logic;
use crate::probe::Probe;
use crate::signal::{get_signal_id, Signal};
use crate::sim_assert_eq;
use crate::simulate::{Sim, Simulation};
use crate::synth::{Synth, VCDValue};
use crate::type_descriptor::TypeDescriptor;

/// The [Constant] wrapper can hold any [Synth] type
/// and store it in a circuit for use by the HDL kernel.
/// This is the easiest way to compute complex constants
/// in your RustHDL constructors, and then store the
/// results inside the circuit for later use.  Unlike
/// [Signal], [Constant] does not have a `.next` field,
/// so you cannot assign to a [Constant] in the HDL
/// kernel (blocked at compile time).  Note that [Constant]
/// does not `impl Default`.  You must construct it
/// with the appropriate value when the circuit is built.
///
/// Here is a correct usage of a [Constant]
/// ```rust
///  use rust_hdl_core::prelude::*;
///
/// #[derive(LogicBlock)]
/// struct AddNum {
///    pub i1: Signal<In, Bits<8>>,
///    pub o1: Signal<Out, Bits<8>>,
///    c1: Constant<Bits<8>>,
/// }
///
/// impl Default for AddNum {
///     fn default() -> Self {
///          Self {
///             i1: Default::default(),
///             o1: Default::default(),
///             c1: Constant::new(42.into()),
///          }
///     }
/// }
///
/// impl Logic for AddNum {
///      #[hdl_gen]
///      fn update(&mut self) {
///         // Note that `self.c1.next` does not exist...
///         self.o1.next = self.i1.val() + self.c1.val();
///      }
/// }
///
///    let mut sim : Simulation<AddNum> = Simulation::default();
///    sim.add_testbench(|mut ep: Sim<AddNum>| {
///        let mut x = ep.init()?;
///        x.i1.next = 13.into();
///        x = ep.wait(1, x)?;
///        sim_assert_eq!(ep, x.o1.val(), 55, x);
///        ep.done(x)
///    });
///    
///    let mut uut = AddNum::default(); uut.connect_all();
///    sim.run(Box::new(uut), 100).unwrap();
///```
#[derive(Copy, Clone, Debug)]
pub struct Constant<T: Synth> {
    val: T,
    id: usize,
}

impl<T: Synth> Constant<T> {
    /// Create a new [Constant] from the given value.
    pub fn new(val: T) -> Constant<T> {
        Constant {
            val,
            id: get_signal_id(),
        }
    }
    /// Retrieve the value of the constant.  Usable in HDL kernels.
    pub fn val(&self) -> T {
        self.val
    }
}

impl<T: Synth> Logic for Constant<T> {
    fn update(&mut self) {}

    fn connect(&mut self) {}
}

impl<T: Synth> Atom for Constant<T> {
    fn bits(&self) -> usize {
        T::BITS
    }

    fn connected(&self) -> bool {
        true
    }

    fn changed(&self) -> bool {
        false
    }

    fn kind(&self) -> AtomKind {
        AtomKind::Constant
    }

    fn descriptor(&self) -> TypeDescriptor {
        T::descriptor()
    }

    fn vcd(&self) -> VCDValue {
        self.val.vcd()
    }

    fn verilog(&self) -> VerilogLiteral {
        self.val.verilog()
    }

    fn id(&self) -> usize {
        self.id
    }

    fn constraints(&self) -> Vec<PinConstraint> {
        vec![]
    }
}

impl<T: Synth> Block for Constant<T> {
    fn connect_all(&mut self) {}

    fn update_all(&mut self) {}

    fn has_changed(&self) -> bool {
        false
    }

    fn accept(&self, name: &str, probe: &mut dyn Probe) {
        probe.visit_atom(name, self);
    }
}