use logicaffeine_verify::ir::VerifyExpr;
use logicaffeine_language::semantics::knowledge_graph::{
HwKnowledgeGraph, KgRelation, HwEntityType, HwRelation,
};
#[derive(Debug, Clone, PartialEq)]
pub enum InvariantSource {
MutexPattern,
HandshakePattern,
PipelineStability,
ResetInit,
}
#[derive(Debug, Clone)]
pub struct CandidateInvariant {
pub expr: VerifyExpr,
pub source: InvariantSource,
pub verified: Option<bool>,
}
pub fn discover_invariants(kg: &HwKnowledgeGraph) -> Vec<CandidateInvariant> {
let mut invariants = Vec::new();
for edge in &kg.edges {
if edge.relation == KgRelation::Constrains {
let p = VerifyExpr::var(&edge.from);
let q = VerifyExpr::var(&edge.to);
invariants.push(CandidateInvariant {
expr: VerifyExpr::not(VerifyExpr::and(p, q)),
source: InvariantSource::MutexPattern,
verified: None,
});
}
}
for edge in &kg.edges {
if edge.relation == KgRelation::Triggers {
let p = VerifyExpr::var(&edge.from);
let q = VerifyExpr::var(&edge.to);
invariants.push(CandidateInvariant {
expr: VerifyExpr::implies(p, q),
source: InvariantSource::HandshakePattern,
verified: None,
});
}
}
for (_, entity) in &kg.entities {
if let HwEntityType::Pipeline { stages, .. } = entity {
for typed_edge in &kg.typed_edges {
if matches!(typed_edge.2, HwRelation::Triggers { .. }) {
let from = VerifyExpr::var(&typed_edge.0);
let to = VerifyExpr::var(&typed_edge.1);
invariants.push(CandidateInvariant {
expr: VerifyExpr::implies(from, to),
source: InvariantSource::PipelineStability,
verified: None,
});
}
}
}
}
for (_, entity) in &kg.entities {
if let HwEntityType::Reset { .. } = entity {
for typed_edge in &kg.typed_edges {
if matches!(typed_edge.2, HwRelation::Resets) {
let rst = VerifyExpr::var(&typed_edge.0);
let state = VerifyExpr::var(&typed_edge.1);
invariants.push(CandidateInvariant {
expr: VerifyExpr::implies(rst, VerifyExpr::not(state)),
source: InvariantSource::ResetInit,
verified: None,
});
}
}
}
}
invariants
}
pub fn verify_invariant(inv: &mut CandidateInvariant, bound: u32) -> bool {
use logicaffeine_verify::consistency::{check_consistency, ConsistencyResult};
let result = check_consistency(&[inv.expr.clone()], &[], bound as usize);
let verified = matches!(result, ConsistencyResult::Consistent);
inv.verified = Some(verified);
verified
}