use super::sva_model::SvaExpr;
#[cfg(feature = "verification")]
use super::hw_pipeline::check_z3_equivalence;
#[derive(Debug, Clone, PartialEq)]
pub enum Divergence {
TooStrong,
TooWeak,
Unknown,
}
#[derive(Debug)]
pub struct RefinementResult {
pub converged: bool,
pub iterations: u32,
pub final_sva: String,
pub divergence: Option<Divergence>,
}
pub fn classify_divergence(
spec_allows_ce: bool,
sva_allows_ce: bool,
) -> Divergence {
match (spec_allows_ce, sva_allows_ce) {
(true, false) => Divergence::TooStrong,
(false, true) => Divergence::TooWeak,
_ => Divergence::Unknown,
}
}
pub fn weaken_implication(sva: &str) -> String {
sva.replace("|->", "|=>")
}
pub fn strengthen_implication(sva: &str) -> String {
sva.replace("|=>", "|->")
}
pub fn weaken_to_eventual(sva: &str) -> String {
if sva.contains("|-> ") && !sva.contains("s_eventually") {
sva.replace("|-> ", "|-> s_eventually(") + ")"
} else {
sva.to_string()
}
}
#[cfg(feature = "verification")]
pub fn refine_sva(spec: &str, initial_sva: &str, clock: &str, bound: u32) -> RefinementResult {
use logicaffeine_verify::equivalence::EquivalenceResult;
let max_iterations: u32 = 5;
let mut current_sva = initial_sva.to_string();
let transformations: Vec<fn(&str) -> String> = vec![
weaken_implication,
strengthen_implication,
weaken_to_eventual,
];
for i in 0..max_iterations {
let result = check_z3_equivalence(spec, ¤t_sva, bound);
match result {
Ok(EquivalenceResult::Equivalent) => {
return RefinementResult {
converged: true,
iterations: i + 1,
final_sva: current_sva,
divergence: None,
};
}
Ok(EquivalenceResult::NotEquivalent { .. }) => {
let transform_idx = i as usize % transformations.len();
let new_sva = transformations[transform_idx](¤t_sva);
if new_sva == current_sva {
if transform_idx + 1 < transformations.len() {
let alt_sva = transformations[transform_idx + 1](¤t_sva);
if alt_sva != current_sva {
current_sva = alt_sva;
continue;
}
}
return RefinementResult {
converged: false,
iterations: i + 1,
final_sva: current_sva,
divergence: Some(Divergence::Unknown),
};
}
current_sva = new_sva;
}
Ok(EquivalenceResult::Unknown) | Err(_) => {
return RefinementResult {
converged: false,
iterations: i + 1,
final_sva: current_sva,
divergence: Some(Divergence::Unknown),
};
}
}
}
RefinementResult {
converged: false,
iterations: max_iterations,
final_sva: current_sva,
divergence: Some(Divergence::Unknown),
}
}