logicaffeine_compile/codegen_sva/
sva_vacuity.rs1use super::sva_model::SvaExpr;
9
10#[derive(Debug, Clone, PartialEq)]
12pub enum VacuityStatus {
13 Nonvacuous,
15 Vacuous,
17 Unknown,
19}
20
21pub fn analyze_vacuity(expr: &SvaExpr) -> VacuityStatus {
30 match expr {
31 SvaExpr::Delay { .. } | SvaExpr::Repetition { .. } |
33 SvaExpr::GotoRepetition { .. } | SvaExpr::NonConsecRepetition { .. } => {
34 VacuityStatus::Nonvacuous
35 }
36
37 SvaExpr::Strong(_) => VacuityStatus::Nonvacuous,
39
40 SvaExpr::Weak(_) => VacuityStatus::Nonvacuous,
42
43 SvaExpr::PropertyNot(inner) => analyze_vacuity(inner),
45
46 SvaExpr::Or(l, r) | SvaExpr::SequenceOr(l, r) | SvaExpr::PropertyIff(l, r) => {
48 match (analyze_vacuity(l), analyze_vacuity(r)) {
49 (VacuityStatus::Nonvacuous, _) | (_, VacuityStatus::Nonvacuous) => {
50 VacuityStatus::Nonvacuous
51 }
52 (VacuityStatus::Vacuous, VacuityStatus::Vacuous) => VacuityStatus::Vacuous,
53 _ => VacuityStatus::Unknown,
54 }
55 }
56
57 SvaExpr::And(l, r) | SvaExpr::SequenceAnd(l, r) => {
59 match (analyze_vacuity(l), analyze_vacuity(r)) {
60 (VacuityStatus::Nonvacuous, _) | (_, VacuityStatus::Nonvacuous) => {
61 VacuityStatus::Nonvacuous
62 }
63 (VacuityStatus::Vacuous, VacuityStatus::Vacuous) => VacuityStatus::Vacuous,
64 _ => VacuityStatus::Unknown,
65 }
66 }
67
68 SvaExpr::IfElse { then_expr, else_expr, .. } => {
70 match (analyze_vacuity(then_expr), analyze_vacuity(else_expr)) {
71 (VacuityStatus::Nonvacuous, _) | (_, VacuityStatus::Nonvacuous) => {
72 VacuityStatus::Nonvacuous
73 }
74 _ => VacuityStatus::Unknown,
75 }
76 }
77
78 SvaExpr::Implication { antecedent, .. } => {
81 match analyze_vacuity(antecedent) {
83 VacuityStatus::Nonvacuous => VacuityStatus::Unknown, VacuityStatus::Vacuous => VacuityStatus::Vacuous,
85 VacuityStatus::Unknown => VacuityStatus::Unknown,
86 }
87 }
88
89 SvaExpr::FollowedBy { antecedent, .. } => {
91 match analyze_vacuity(antecedent) {
92 VacuityStatus::Nonvacuous => VacuityStatus::Unknown,
93 VacuityStatus::Vacuous => VacuityStatus::Vacuous,
94 VacuityStatus::Unknown => VacuityStatus::Unknown,
95 }
96 }
97
98 SvaExpr::Nexttime(inner, _) | SvaExpr::SNexttime(inner, _) => {
100 analyze_vacuity(inner)
101 }
102
103 SvaExpr::Always(inner) | SvaExpr::SAlways(inner) => {
105 analyze_vacuity(inner)
106 }
107
108 SvaExpr::AlwaysBounded { body, .. } | SvaExpr::SAlwaysBounded { body, .. } => {
110 analyze_vacuity(body)
111 }
112
113 SvaExpr::SEventually(inner) => analyze_vacuity(inner),
115
116 SvaExpr::EventuallyBounded { body, .. } | SvaExpr::SEventuallyBounded { body, .. } => {
118 analyze_vacuity(body)
119 }
120
121 SvaExpr::Until { .. } => VacuityStatus::Nonvacuous,
123
124 SvaExpr::PropertyImplies(lhs, _) => {
126 match analyze_vacuity(lhs) {
127 VacuityStatus::Nonvacuous => VacuityStatus::Unknown, VacuityStatus::Vacuous => VacuityStatus::Vacuous,
129 VacuityStatus::Unknown => VacuityStatus::Unknown,
130 }
131 }
132
133 SvaExpr::DisableIff { body, .. } => {
135 analyze_vacuity(body)
136 }
137
138 SvaExpr::PropertyCase { default, .. } => {
142 if default.is_some() {
143 VacuityStatus::Nonvacuous
145 } else {
146 VacuityStatus::Unknown
148 }
149 }
150
151 SvaExpr::Signal(_) | SvaExpr::Const(_, _) |
153 SvaExpr::Rose(_) | SvaExpr::Fell(_) | SvaExpr::Past(_, _) |
154 SvaExpr::Stable(_) | SvaExpr::Changed(_) |
155 SvaExpr::Not(_) | SvaExpr::Eq(_, _) | SvaExpr::NotEq(_, _) |
156 SvaExpr::LessThan(_, _) | SvaExpr::GreaterThan(_, _) |
157 SvaExpr::LessEqual(_, _) | SvaExpr::GreaterEqual(_, _) |
158 SvaExpr::Ternary { .. } |
159 SvaExpr::OneHot0(_) | SvaExpr::OneHot(_) | SvaExpr::CountOnes(_) |
160 SvaExpr::IsUnknown(_) | SvaExpr::Sampled(_) | SvaExpr::Bits(_) | SvaExpr::Clog2(_) |
161 SvaExpr::CountBits(_, _) | SvaExpr::IsUnbounded(_) |
162 SvaExpr::AcceptOn { .. } | SvaExpr::RejectOn { .. } |
163 SvaExpr::SyncAcceptOn { .. } | SvaExpr::SyncRejectOn { .. } |
164 SvaExpr::FirstMatch(_) | SvaExpr::Throughout { .. } | SvaExpr::Within { .. } |
165 SvaExpr::Intersect { .. } |
166 SvaExpr::BitAnd(_, _) | SvaExpr::BitOr(_, _) | SvaExpr::BitXor(_, _) |
167 SvaExpr::BitNot(_) | SvaExpr::ReductionAnd(_) | SvaExpr::ReductionOr(_) |
168 SvaExpr::ReductionXor(_) | SvaExpr::BitSelect { .. } | SvaExpr::PartSelect { .. } |
169 SvaExpr::Concat(_) | SvaExpr::ConstCast(_) |
170 SvaExpr::FieldAccess { .. } | SvaExpr::EnumLiteral { .. } |
171 SvaExpr::Triggered(_) | SvaExpr::Matched(_) |
172 SvaExpr::ImmediateAssert { .. } |
173 SvaExpr::SequenceAction { .. } |
174 SvaExpr::Clocked { .. } |
175 SvaExpr::LocalVar(_) |
176 SvaExpr::ArrayMap { .. } |
177 SvaExpr::TypeThis |
178 SvaExpr::RealConst(_) => {
179 VacuityStatus::Nonvacuous
180 }
181 }
182}
183
184pub fn is_dead_assertion(expr: &SvaExpr) -> bool {
187 matches!(analyze_vacuity(expr), VacuityStatus::Vacuous)
188}