Skip to content

Commit 43f4feb

Browse files
committed
Update cexenum tool to latest version
1 parent 117fb26 commit 43f4feb

File tree

4 files changed

+1073
-83
lines changed

4 files changed

+1073
-83
lines changed

tools/aigcexmin/src/aig_eval.rs

+11
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@ pub trait AigValue<Context>: Copy {
66
fn invert_if(self, en: bool, ctx: &mut Context) -> Self;
77
fn and(self, other: Self, ctx: &mut Context) -> Self;
88
fn constant(value: bool, ctx: &mut Context) -> Self;
9+
10+
fn invert(self, ctx: &mut Context) -> Self {
11+
self.invert_if(true, ctx)
12+
}
13+
14+
fn or(self, other: Self, ctx: &mut Context) -> Self {
15+
let not_self = self.invert(ctx);
16+
let not_other = other.invert(ctx);
17+
let not_or = not_self.and(not_other, ctx);
18+
not_or.invert(ctx)
19+
}
920
}
1021

1122
pub fn initial_frame<L, V, Context>(

tools/aigcexmin/src/care_graph.rs

+41-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,15 @@ pub struct NodeRef {
2323

2424
impl std::fmt::Debug for NodeRef {
2525
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26-
f.debug_tuple("NodeRef::new").field(&self.index()).finish()
26+
if self.is_const() {
27+
if *self == Self::TRUE {
28+
f.debug_struct("NodeRef::TRUE").finish()
29+
} else {
30+
f.debug_struct("NodeRef::FALSE").finish()
31+
}
32+
} else {
33+
f.debug_tuple("NodeRef::new").field(&self.index()).finish()
34+
}
2735
}
2836
}
2937

@@ -48,6 +56,10 @@ impl NodeRef {
4856
pub fn index(self) -> usize {
4957
!(self.code.0.get()) as usize
5058
}
59+
60+
pub fn is_const(self) -> bool {
61+
self == Self::TRUE || self == Self::FALSE
62+
}
5163
}
5264

5365
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
@@ -348,7 +360,10 @@ impl AndOrGraph {
348360
}
349361
};
350362

351-
if shuffle > 0 && output != NodeRef::FALSE && output != NodeRef::TRUE {
363+
if (shuffle > 0 || new_inputs != inputs)
364+
&& output != NodeRef::FALSE
365+
&& output != NodeRef::TRUE
366+
{
352367
if let Ok((gate, inputs)) = self.nodes[output.index()].def.as_gate() {
353368
let [a, b] = inputs.map(|input| self.nodes[input.index()].priority);
354369

@@ -438,6 +453,7 @@ pub enum Verification {
438453

439454
pub struct MinimizationOptions {
440455
pub fixed_init: bool,
456+
pub satisfy_assumptions: bool,
441457
pub verify: Option<Verification>,
442458
}
443459

@@ -509,6 +525,7 @@ pub fn minimize<L: Lit>(
509525
);
510526

511527
let mut minimization_target = 'minimization_target: {
528+
let mut invariant_failed = (Some(false), NodeRef::TRUE);
512529
for (t, inputs) in frame_inputs.iter().enumerate() {
513530
if t > 0 {
514531
successor_frame(
@@ -527,18 +544,29 @@ pub fn minimize<L: Lit>(
527544
&mut graph,
528545
);
529546
}
547+
548+
if options.satisfy_assumptions {
549+
for invariant in aig.invariant_constraints.iter() {
550+
let (var, polarity) = unpack_lit(*invariant);
551+
let inv_invariant = state[var].invert_if(!polarity, &mut graph);
552+
553+
invariant_failed = invariant_failed.or(inv_invariant, &mut graph);
554+
}
555+
}
556+
530557
let mut good_state = (Some(true), NodeRef::TRUE);
531558

532559
for (i, bad) in aig.bad_state_properties.iter().enumerate() {
533560
let (var, polarity) = unpack_lit(*bad);
534561
let inv_bad = state[var].invert_if(!polarity, &mut graph);
535562

536-
if inv_bad.0 == Some(false) {
563+
if inv_bad.0 == Some(false) && invariant_failed.0 == Some(false) {
537564
println!("bad state property {i} active in frame {t}");
538565
}
539566

540567
good_state = good_state.and(inv_bad, &mut graph);
541568
}
569+
good_state = good_state.or(invariant_failed, &mut graph);
542570
if good_state.0 == Some(false) {
543571
println!("bad state found in frame {t}");
544572

@@ -691,6 +719,16 @@ pub fn minimize<L: Lit>(
691719
);
692720
}
693721

722+
if options.satisfy_assumptions {
723+
for invariant in aig.invariant_constraints.iter() {
724+
let (var, polarity) = unpack_lit(*invariant);
725+
let invariant_output = check_state[var].invert_if(polarity, &mut ());
726+
if invariant_output != Some(true) {
727+
break 'frame;
728+
}
729+
}
730+
}
731+
694732
for bad in aig.bad_state_properties.iter() {
695733
let (var, polarity) = unpack_lit(*bad);
696734
let bad_output = check_state[var].invert_if(polarity, &mut ());

tools/aigcexmin/src/main.rs

+5
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ pub struct Options {
4141
/// initialization but instead perform initialization using inputs in the first frame.
4242
#[clap(long)]
4343
latches: bool,
44+
45+
/// Require assumptions to stay satisfied during minimization
46+
#[clap(long)]
47+
satisfy_assumptions: bool
4448
}
4549

4650
#[derive(Copy, Clone, ValueEnum)]
@@ -133,6 +137,7 @@ fn main() -> color_eyre::Result<()> {
133137
&mut writer_output,
134138
&care_graph::MinimizationOptions {
135139
fixed_init: !options.latches,
140+
satisfy_assumptions: options.satisfy_assumptions,
136141
verify: match options.verify {
137142
VerificationOption::Off => None,
138143
VerificationOption::Cex => Some(care_graph::Verification::Cex),

0 commit comments

Comments
 (0)