Skip to main content

litex/verify/
verify_fact_well_defined.rs

1use crate::prelude::*;
2
3// well-defined check for fact: 1. predicate is defined 2. all args are well-defined
4// store verified related facts during the verification process, e.g. when verifying f(a)(b) is well-defined, we store f(a) in the set where f returns, and store f(a)(b) in the set where f(a) returns
5impl Runtime {
6    pub fn verify_fact_well_defined(
7        &mut self,
8        fact: &Fact,
9        verify_state: &VerifyState,
10    ) -> Result<(), RuntimeError> {
11        match fact {
12            Fact::AtomicFact(atomic_fact) => {
13                self.verify_atomic_fact_well_defined(atomic_fact, verify_state)
14            }
15            Fact::AndFact(and_fact) => self.verify_and_fact_well_defined(and_fact, verify_state),
16            Fact::ChainFact(chain_fact) => {
17                self.verify_chain_fact_well_defined(chain_fact, verify_state)
18            }
19            Fact::OrFact(or_fact) => self.verify_or_fact_well_defined(or_fact, verify_state),
20            Fact::ExistFact(exist_fact) => {
21                self.verify_exist_fact_well_defined(exist_fact, verify_state)
22            }
23            Fact::ForallFact(forall_fact) => {
24                self.verify_forall_fact_well_defined(forall_fact, verify_state)
25            }
26            Fact::ForallFactWithIff(forall_fact_with_iff) => {
27                self.verify_forall_fact_with_iff_well_defined(forall_fact_with_iff, verify_state)
28            }
29            Fact::NotForall(not_forall) => {
30                self.verify_not_forall_fact_well_defined(not_forall, verify_state)
31            }
32        }
33    }
34
35    pub fn verify_atomic_fact_well_defined(
36        &mut self,
37        atomic_fact: &AtomicFact,
38        verify_state: &VerifyState,
39    ) -> Result<(), RuntimeError> {
40        match atomic_fact {
41            AtomicFact::EqualFact(equal_fact) => {
42                self.verify_equal_fact_well_defined(equal_fact, verify_state)
43            }
44            _ => self.verify_non_equational_atomic_fact_well_defined(atomic_fact, verify_state),
45        }
46    }
47
48    fn verify_equal_fact_well_defined(
49        &mut self,
50        equal_fact: &EqualFact,
51        verify_state: &VerifyState,
52    ) -> Result<(), RuntimeError> {
53        self.verify_obj_well_defined_and_store_cache(&equal_fact.left, verify_state)?;
54        self.verify_obj_well_defined_and_store_cache(&equal_fact.right, verify_state)?;
55        Ok(())
56    }
57
58    fn verify_non_equational_atomic_fact_well_defined(
59        &mut self,
60        atomic_fact: &AtomicFact,
61        verify_state: &VerifyState,
62    ) -> Result<(), RuntimeError> {
63        // 1. predicate is defined, expected args length is equal to actual args length
64        let name_string = atomic_fact.key();
65        if is_builtin_predicate(&name_string) {
66            let expected_len = atomic_fact.is_builtin_predicate_and_return_expected_args_len();
67            let actual_args = atomic_fact.args();
68            if actual_args.len() != expected_len {
69                return Err(WellDefinedRuntimeError(
70                    RuntimeErrorStruct::new_with_msg_and_line_file(
71                        format!(
72                            "fact `{}` expects {} argument(s), but got {}",
73                            name_string,
74                            expected_len,
75                            actual_args.len()
76                        ),
77                        atomic_fact.line_file(),
78                    ),
79                )
80                .into());
81            }
82        } else {
83            let expected_len = if let Some(predicate_definition) =
84                self.get_prop_definition_by_name(&name_string)
85            {
86                predicate_definition.params_def_with_type.number_of_params()
87            } else if let Some(abstract_prop_definition) =
88                self.get_abstract_prop_definition_by_name(&name_string)
89            {
90                abstract_prop_definition.params.len()
91            } else {
92                return Err(WellDefinedRuntimeError(
93                    RuntimeErrorStruct::new_with_msg_and_line_file(
94                        format!("fact `{}` not defined", name_string),
95                        atomic_fact.line_file(),
96                    ),
97                )
98                .into());
99            };
100
101            let actual_args = atomic_fact.args();
102            if actual_args.len() != expected_len {
103                return Err(WellDefinedRuntimeError(
104                    RuntimeErrorStruct::new_with_msg_and_line_file(
105                        format!(
106                            "fact `{}` expects {} argument(s), but got {}",
107                            name_string,
108                            expected_len,
109                            actual_args.len()
110                        ),
111                        atomic_fact.line_file(),
112                    ),
113                )
114                .into());
115            }
116        }
117
118        // 2. all args are well-defined
119        for arg in atomic_fact.args() {
120            self.verify_obj_well_defined_and_store_cache(&arg, verify_state)?;
121        }
122
123        Ok(())
124    }
125
126    pub fn verify_and_fact_well_defined(
127        &mut self,
128        and_fact: &AndFact,
129        verify_state: &VerifyState,
130    ) -> Result<(), RuntimeError> {
131        for fact in and_fact.facts.iter() {
132            self.verify_atomic_fact_well_defined(fact, verify_state)?;
133        }
134        Ok(())
135    }
136
137    pub fn verify_chain_fact_well_defined(
138        &mut self,
139        chain_fact: &ChainFact,
140        verify_state: &VerifyState,
141    ) -> Result<(), RuntimeError> {
142        let facts = chain_fact.facts()?;
143        for fact in facts.iter() {
144            self.verify_atomic_fact_well_defined(fact, verify_state)?;
145        }
146        Ok(())
147    }
148
149    pub fn verify_or_fact_well_defined(
150        &mut self,
151        or_fact: &OrFact,
152        verify_state: &VerifyState,
153    ) -> Result<(), RuntimeError> {
154        for fact in or_fact.facts.iter() {
155            self.verify_and_chain_atomic_fact_well_defined(fact, verify_state)?;
156        }
157        Ok(())
158    }
159
160    fn verify_and_chain_atomic_fact_well_defined(
161        &mut self,
162        fact: &AndChainAtomicFact,
163        verify_state: &VerifyState,
164    ) -> Result<(), RuntimeError> {
165        match fact {
166            AndChainAtomicFact::AtomicFact(a) => {
167                self.verify_atomic_fact_well_defined(a, verify_state)?
168            }
169            AndChainAtomicFact::AndFact(a) => self.verify_and_fact_well_defined(a, verify_state)?,
170            AndChainAtomicFact::ChainFact(c) => {
171                self.verify_chain_fact_well_defined(c, verify_state)?
172            }
173        }
174        Ok(())
175    }
176
177    pub fn verify_exist_fact_well_defined(
178        &mut self,
179        exist_fact: &ExistFactEnum,
180        verify_state: &VerifyState,
181    ) -> Result<(), RuntimeError> {
182        self.run_in_local_env(|rt| {
183            if let Err(e) = rt.define_params_with_type(
184                exist_fact.params_def_with_type(),
185                false,
186                ParamObjType::Exist,
187            ) {
188                return Err(WellDefinedRuntimeError(RuntimeErrorStruct::new(
189                    None,
190                    "failed to define parameters in exist fact".to_string(),
191                    exist_fact.line_file(),
192                    Some(e),
193                    vec![],
194                ))
195                .into());
196            }
197
198            for fact in exist_fact.facts() {
199                match fact {
200                    ExistBodyFact::AtomicFact(f) => {
201                        let body_fact = OrAndChainAtomicFact::AtomicFact(f.clone());
202                        rt.verify_or_and_chain_atomic_fact_well_defined(&body_fact, verify_state)?;
203                        rt.store_or_and_chain_atomic_fact_without_well_defined_verified_and_infer(
204                            body_fact,
205                        )?;
206                    }
207                    ExistBodyFact::AndFact(f) => {
208                        let body_fact = OrAndChainAtomicFact::AndFact(f.clone());
209                        rt.verify_or_and_chain_atomic_fact_well_defined(&body_fact, verify_state)?;
210                        rt.store_or_and_chain_atomic_fact_without_well_defined_verified_and_infer(
211                            body_fact,
212                        )?;
213                    }
214                    ExistBodyFact::ChainFact(f) => {
215                        let body_fact = OrAndChainAtomicFact::ChainFact(f.clone());
216                        rt.verify_or_and_chain_atomic_fact_well_defined(&body_fact, verify_state)?;
217                        rt.store_or_and_chain_atomic_fact_without_well_defined_verified_and_infer(
218                            body_fact,
219                        )?;
220                    }
221                    ExistBodyFact::OrFact(f) => {
222                        let body_fact = OrAndChainAtomicFact::OrFact(f.clone());
223                        rt.verify_or_and_chain_atomic_fact_well_defined(&body_fact, verify_state)?;
224                        rt.store_or_and_chain_atomic_fact_without_well_defined_verified_and_infer(
225                            body_fact,
226                        )?;
227                    }
228                    ExistBodyFact::InlineForall(f) => {
229                        rt.verify_forall_fact_well_defined(f, verify_state)?;
230                        rt.store_forall_fact_without_well_defined_verified_and_infer(f.clone())?;
231                    }
232                }
233            }
234            Ok(())
235        })
236    }
237
238    pub fn verify_forall_fact_well_defined(
239        &mut self,
240        forall_fact: &ForallFact,
241        verify_state: &VerifyState,
242    ) -> Result<(), RuntimeError> {
243        self.run_in_local_env(|rt| {
244            rt.verify_forall_fact_well_defined_inner(forall_fact, verify_state)
245        })
246    }
247
248    pub fn verify_forall_fact_params_and_dom_well_defined(
249        &mut self,
250        forall_fact: &ForallFact,
251        verify_state: &VerifyState,
252    ) -> Result<(), RuntimeError> {
253        self.run_in_local_env(|rt| {
254            rt.verify_forall_fact_params_and_dom_well_defined_inner(forall_fact, verify_state)
255        })
256    }
257
258    fn verify_forall_fact_params_and_dom_well_defined_inner(
259        &mut self,
260        forall_fact: &ForallFact,
261        verify_state: &VerifyState,
262    ) -> Result<(), RuntimeError> {
263        if let Err(e) = self.define_params_with_type(
264            &forall_fact.params_def_with_type,
265            false,
266            ParamObjType::Forall,
267        ) {
268            return Err(WellDefinedRuntimeError(RuntimeErrorStruct::new(
269                None,
270                "failed to define parameters in forall fact".to_string(),
271                forall_fact.line_file.clone(),
272                Some(e),
273                vec![],
274            ))
275            .into());
276        }
277
278        for dom_fact in forall_fact.dom_facts.iter() {
279            if let Err(exec_stmt_error) =
280                self.verify_fact_well_defined_and_store_and_infer(dom_fact.clone(), verify_state)
281            {
282                return Err(WellDefinedRuntimeError(RuntimeErrorStruct::new(
283                    None,
284                    String::new(),
285                    dom_fact.line_file(),
286                    Some(exec_stmt_error),
287                    vec![],
288                ))
289                .into());
290            }
291        }
292        Ok(())
293    }
294
295    fn verify_forall_fact_well_defined_inner(
296        &mut self,
297        forall_fact: &ForallFact,
298        verify_state: &VerifyState,
299    ) -> Result<(), RuntimeError> {
300        self.verify_forall_fact_params_and_dom_well_defined_inner(forall_fact, verify_state)?;
301        for fact in forall_fact.then_facts.iter() {
302            if let Err(exec_stmt_error) = self
303                .verify_exist_or_and_chain_atomic_fact_well_defined_and_store_and_infer(
304                    fact,
305                    verify_state,
306                )
307            {
308                return Err(WellDefinedRuntimeError(RuntimeErrorStruct::new(
309                    None,
310                    String::new(),
311                    fact.line_file(),
312                    Some(exec_stmt_error),
313                    vec![],
314                ))
315                .into());
316            }
317        }
318        Ok(())
319    }
320
321    pub fn verify_or_and_chain_atomic_fact_well_defined(
322        &mut self,
323        fact: &OrAndChainAtomicFact,
324        verify_state: &VerifyState,
325    ) -> Result<(), RuntimeError> {
326        match fact {
327            OrAndChainAtomicFact::AtomicFact(a) => {
328                self.verify_atomic_fact_well_defined(a, verify_state)?
329            }
330            OrAndChainAtomicFact::AndFact(a) => {
331                self.verify_and_fact_well_defined(a, verify_state)?
332            }
333            OrAndChainAtomicFact::ChainFact(c) => {
334                self.verify_chain_fact_well_defined(c, verify_state)?
335            }
336            OrAndChainAtomicFact::OrFact(o) => self.verify_or_fact_well_defined(o, verify_state)?,
337        }
338        Ok(())
339    }
340
341    pub fn verify_exist_or_and_chain_atomic_fact_well_defined(
342        &mut self,
343        fact: &ExistOrAndChainAtomicFact,
344        verify_state: &VerifyState,
345    ) -> Result<(), RuntimeError> {
346        match fact {
347            ExistOrAndChainAtomicFact::AtomicFact(a) => {
348                self.verify_atomic_fact_well_defined(a, verify_state)?
349            }
350            ExistOrAndChainAtomicFact::AndFact(a) => {
351                self.verify_and_fact_well_defined(a, verify_state)?
352            }
353            ExistOrAndChainAtomicFact::ChainFact(c) => {
354                self.verify_chain_fact_well_defined(c, verify_state)?
355            }
356            ExistOrAndChainAtomicFact::OrFact(o) => {
357                self.verify_or_fact_well_defined(o, verify_state)?
358            }
359            ExistOrAndChainAtomicFact::ExistFact(e) => {
360                self.verify_exist_fact_well_defined(e, verify_state)?
361            }
362        }
363        Ok(())
364    }
365
366    pub fn verify_forall_fact_with_iff_well_defined(
367        &mut self,
368        forall_fact_with_iff: &ForallFactWithIff,
369        verify_state: &VerifyState,
370    ) -> Result<(), RuntimeError> {
371        self.run_in_local_env(|rt| {
372            rt.verify_forall_fact_well_defined_inner(
373                &forall_fact_with_iff.forall_fact,
374                verify_state,
375            )?;
376            for fact in forall_fact_with_iff.iff_facts.iter() {
377                rt.verify_exist_or_and_chain_atomic_fact_well_defined(fact, verify_state)?;
378            }
379            Ok(())
380        })
381    }
382
383    pub fn verify_not_forall_fact_well_defined(
384        &mut self,
385        not_forall: &NotForallFact,
386        verify_state: &VerifyState,
387    ) -> Result<(), RuntimeError> {
388        self.verify_forall_fact_well_defined(&not_forall.forall_fact, verify_state)
389    }
390}