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
use crate::block::Block;
use crate::check_connected::check_connected;
use crate::check_logic_loops::check_logic_loops;
use crate::check_write_inputs::check_inputs_not_written;

use std::collections::HashMap;

/// A map of open connections, hashed on the signal ID
pub type OpenMap = HashMap<usize, PathedName>;

/// Struct to capture a signal in the design for human consumption
#[derive(Clone, Debug, PartialEq)]
pub struct PathedName {
    /// The path to the signal (i.e., the hierarchical namespace such as `uut:flasher:blah`)
    pub path: String,
    /// The name of the signal that is being referenced, such as `pulse_in`.
    pub name: String,
}

/// A list of [PathedName]
pub type PathedNameList = Vec<PathedName>;

/// The enum models the errors that can be returned from "checking"
/// a circuit using [check_all].
#[derive(Debug, Clone, PartialEq)]
pub enum CheckError {
    /// The check failed because of one or more open signals (described by the [OpenMap])
    OpenSignal(OpenMap),
    /// The circuit contains logical loops (i.e., `A <- B <- A`), and will not simulate
    LogicLoops(PathedNameList),
    /// The circuit attempts to write to the inputs, which is not allowed in RustHDL.
    WritesToInputs(PathedNameList),
}

/// This is a helper function used to check a [Block] for connection, loops, and
/// writes to the inputs.  
/// ```rust
/// use rust_hdl_core::prelude::*;
///
/// #[derive(LogicBlock, Default)]
/// struct Circuit {
///    pub in1: Signal<In, Bit>,
///    pub out1: Signal<Out, Bit>,
/// }
///
/// impl Logic for Circuit {
///    #[hdl_gen]
///    fn update(&mut self) {
///         self.out1.next = !self.in1.val();
///    }
/// }
///
/// let mut uut = Circuit::default();  uut.connect_all();
/// assert!(check_all(&uut).is_ok());
/// ```
pub fn check_all(uut: &dyn Block) -> Result<(), CheckError> {
    check_connected(uut)?;
    check_logic_loops(uut)?;
    check_inputs_not_written(uut)?;
    Ok(())
}