logicaffeine_compile/codegen_sva/
synthesis_refine.rs1use super::sva_model::SvaExpr;
7
8#[cfg(feature = "verification")]
9use super::hw_pipeline::check_z3_equivalence;
10
11#[derive(Debug, Clone, PartialEq)]
13pub enum Divergence {
14 TooStrong,
16 TooWeak,
18 Unknown,
20}
21
22#[derive(Debug)]
24pub struct RefinementResult {
25 pub converged: bool,
26 pub iterations: u32,
27 pub final_sva: String,
28 pub divergence: Option<Divergence>,
29}
30
31pub fn classify_divergence(
36 spec_allows_ce: bool,
37 sva_allows_ce: bool,
38) -> Divergence {
39 match (spec_allows_ce, sva_allows_ce) {
40 (true, false) => Divergence::TooStrong,
41 (false, true) => Divergence::TooWeak,
42 _ => Divergence::Unknown,
43 }
44}
45
46pub fn weaken_implication(sva: &str) -> String {
49 sva.replace("|->", "|=>")
50}
51
52pub fn strengthen_implication(sva: &str) -> String {
55 sva.replace("|=>", "|->")
56}
57
58pub fn weaken_to_eventual(sva: &str) -> String {
61 if sva.contains("|-> ") && !sva.contains("s_eventually") {
62 sva.replace("|-> ", "|-> s_eventually(") + ")"
63 } else {
64 sva.to_string()
65 }
66}
67
68#[cfg(feature = "verification")]
71pub fn refine_sva(spec: &str, initial_sva: &str, clock: &str, bound: u32) -> RefinementResult {
72 use logicaffeine_verify::equivalence::EquivalenceResult;
73
74 let max_iterations: u32 = 5;
75 let mut current_sva = initial_sva.to_string();
76 let transformations: Vec<fn(&str) -> String> = vec![
77 weaken_implication,
78 strengthen_implication,
79 weaken_to_eventual,
80 ];
81
82 for i in 0..max_iterations {
83 let result = check_z3_equivalence(spec, ¤t_sva, bound);
84 match result {
85 Ok(EquivalenceResult::Equivalent) => {
86 return RefinementResult {
87 converged: true,
88 iterations: i + 1,
89 final_sva: current_sva,
90 divergence: None,
91 };
92 }
93 Ok(EquivalenceResult::NotEquivalent { .. }) => {
94 let transform_idx = i as usize % transformations.len();
96 let new_sva = transformations[transform_idx](¤t_sva);
97 if new_sva == current_sva {
98 if transform_idx + 1 < transformations.len() {
100 let alt_sva = transformations[transform_idx + 1](¤t_sva);
101 if alt_sva != current_sva {
102 current_sva = alt_sva;
103 continue;
104 }
105 }
106 return RefinementResult {
108 converged: false,
109 iterations: i + 1,
110 final_sva: current_sva,
111 divergence: Some(Divergence::Unknown),
112 };
113 }
114 current_sva = new_sva;
115 }
116 Ok(EquivalenceResult::Unknown) | Err(_) => {
117 return RefinementResult {
118 converged: false,
119 iterations: i + 1,
120 final_sva: current_sva,
121 divergence: Some(Divergence::Unknown),
122 };
123 }
124 }
125 }
126
127 RefinementResult {
128 converged: false,
129 iterations: max_iterations,
130 final_sva: current_sva,
131 divergence: Some(Divergence::Unknown),
132 }
133}