safety_net/
logic.rs

1/*!
2
3  Four-state logic
4
5*/
6
7use std::{fmt, str::FromStr};
8
9use crate::error::Error;
10
11#[derive(Debug, Clone, PartialEq, Eq, Copy)]
12#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
13/// An enum to represent four-state logic
14pub enum Logic {
15    /// Logical zero
16    False,
17    /// Logical one
18    True,
19    /// Don't care
20    X,
21    /// High-impedance state
22    Z,
23}
24
25impl Logic {
26    /// Get logic as bool
27    pub fn unwrap(self) -> bool {
28        match self {
29            Logic::True => true,
30            Logic::False => false,
31            _ => panic!("Logic is not truthy"),
32        }
33    }
34
35    /// Get logic as bool with failure `msg`
36    pub fn expect(self, msg: &str) -> bool {
37        match self {
38            Logic::True => true,
39            Logic::False => false,
40            _ => panic!("{}", msg),
41        }
42    }
43
44    /// Returns [prim@true] if the logic is a don't care
45    pub fn is_dont_care(&self) -> bool {
46        matches!(self, Logic::X)
47    }
48
49    /// Returns the logic as a string
50    pub fn as_str(&self) -> &str {
51        match self {
52            Logic::True => "1'b1",
53            Logic::False => "1'b0",
54            Logic::X => "1'bx",
55            Logic::Z => "1'bz",
56        }
57    }
58
59    /// Create a four-state logic element from a boolean
60    pub fn from_bool(b: bool) -> Logic {
61        if b { Logic::True } else { Logic::False }
62    }
63}
64
65impl std::ops::BitAnd for Logic {
66    type Output = Self;
67
68    fn bitand(self, rhs: Self) -> Self::Output {
69        match (self, rhs) {
70            (Logic::False, _) | (_, Logic::False) => Logic::False,
71            (Logic::True, Logic::True) => Logic::True,
72            (Logic::True, Logic::Z) | (Logic::Z, Logic::True) => Logic::X,
73            (Logic::X, _) | (_, Logic::X) | (Logic::Z, Logic::Z) => Logic::X,
74        }
75    }
76}
77
78impl std::ops::BitOr for Logic {
79    type Output = Self;
80
81    fn bitor(self, rhs: Self) -> Self::Output {
82        match (self, rhs) {
83            (Logic::True, _) | (_, Logic::True) => Logic::True,
84            (Logic::False, Logic::False) => Logic::False,
85            _ => Logic::X,
86        }
87    }
88}
89
90impl std::ops::Not for Logic {
91    type Output = Self;
92
93    fn not(self) -> Self::Output {
94        match self {
95            Logic::False => Logic::True,
96            Logic::True => Logic::False,
97            _ => Logic::X,
98        }
99    }
100}
101
102impl fmt::Display for Logic {
103    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104        match self {
105            Logic::True => write!(f, "1'b1"),
106            Logic::False => write!(f, "1'b0"),
107            Logic::X => write!(f, "1'bx"),
108            Logic::Z => write!(f, "1'bz"),
109        }
110    }
111}
112
113impl From<bool> for Logic {
114    fn from(value: bool) -> Self {
115        if value { Logic::True } else { Logic::False }
116    }
117}
118
119impl FromStr for Logic {
120    type Err = Error;
121
122    fn from_str(s: &str) -> Result<Self, Self::Err> {
123        match s {
124            "1'b1" | "1'h1" => Ok(Logic::True),
125            "1'b0" | "1'h0" => Ok(Logic::False),
126            "1'bx" | "1'hx" => Ok(Logic::X),
127            "1'bz" | "1'hz" => Ok(Logic::Z),
128            _ => Err(Error::ParseError(s.to_string())),
129        }
130    }
131}
132
133/// Create a [Logic::True] instance
134pub fn r#true() -> Logic {
135    Logic::True
136}
137
138/// Create a [Logic::False] instance
139pub fn r#false() -> Logic {
140    Logic::False
141}
142
143/// Create a don't care instance
144pub fn dont_care() -> Logic {
145    Logic::X
146}
147
148/// Create a high-impedance instance
149pub fn high_z() -> Logic {
150    Logic::Z
151}