diff --git a/regression/ebmc/k-induction/k-induction6.desc b/regression/ebmc/k-induction/k-induction6.desc index 7b106e61..0d32dc6e 100644 --- a/regression/ebmc/k-induction/k-induction6.desc +++ b/regression/ebmc/k-induction/k-induction6.desc @@ -1,9 +1,10 @@ -KNOWNBUG +CORE k-induction6.sv - +--k-induction +^\[main\.a0\] always not s_eventually !main\.x: FAILURE: property unsupported by k-induction$ +^\[main\.p0\] always main\.x: INCONCLUSIVE$ ^EXIT=10$ ^SIGNAL=0$ -- ^warning: ignoring -- -The property should hold, but is reported as refuted. diff --git a/regression/ebmc/k-induction/k-induction7.desc b/regression/ebmc/k-induction/k-induction7.desc new file mode 100644 index 00000000..e677a5e0 --- /dev/null +++ b/regression/ebmc/k-induction/k-induction7.desc @@ -0,0 +1,11 @@ +CORE +k-induction7.sv +--k-induction +^\[main\.a0\] always not s_eventually !main\.y: FAILURE: property unsupported by k-induction$ +^\[main\.a1\] always !main\.x: ASSUMED$ +^\[main\.p0\] always !main\.z: PROVED$ +^EXIT=0$ +^SIGNAL=0$ +-- +^warning: ignoring +-- diff --git a/regression/ebmc/k-induction/k-induction7.sv b/regression/ebmc/k-induction/k-induction7.sv new file mode 100644 index 00000000..c48fbb15 --- /dev/null +++ b/regression/ebmc/k-induction/k-induction7.sv @@ -0,0 +1,15 @@ +module main(input clk, input x, input y); + + reg z = 0; + always_ff @(posedge clk) z <= z || x; + + // unsupported assumption + a0: assume property (not s_eventually !y); + + // supported assumption + a1: assume property (!x); + + // inductive property + p0: assert property (!z); + +endmodule diff --git a/src/ebmc/ebmc_properties.cpp b/src/ebmc/ebmc_properties.cpp index daa0d07c..5ad2db6b 100644 --- a/src/ebmc/ebmc_properties.cpp +++ b/src/ebmc/ebmc_properties.cpp @@ -78,9 +78,9 @@ ebmc_propertiest ebmc_propertiest::from_transition_system( id2string(symbol.location.get_comment()); // Don't try to prove assumption properties. - if(symbol.value.id() == ID_sva_assume) + if(properties.properties.back().is_assumption()) { - properties.properties.back().status = propertyt::statust::ASSUMED; + properties.properties.back().assumed(); properties.properties.back().normalized_expr = normalize_property(to_sva_assume_expr(symbol.value).op()); } diff --git a/src/ebmc/ebmc_properties.h b/src/ebmc/ebmc_properties.h index 8ebd1c86..7b245e0d 100644 --- a/src/ebmc/ebmc_properties.h +++ b/src/ebmc/ebmc_properties.h @@ -103,6 +103,11 @@ class ebmc_propertiest return status == statust::INCONCLUSIVE; } + void assumed() + { + status = statust::ASSUMED; + } + void unknown() { status = statust::UNKNOWN; @@ -164,6 +169,11 @@ class ebmc_propertiest { return ::is_exists_path(original_expr); } + + bool is_assumption() const + { + return original_expr.id() == ID_sva_assume; + } }; typedef std::list propertiest; @@ -209,11 +219,18 @@ class ebmc_propertiest return result; } - void reset_failure_to_unknown() + /// Resets properties/assumptions in FAILURE state to + /// ASSUMED/UNKNOWN respectively. + void reset_failure() { for(auto &p : properties) if(p.is_failure()) - p.unknown(); + { + if(p.is_assumption()) + p.assumed(); + else + p.unknown(); + } } }; diff --git a/src/ebmc/k_induction.cpp b/src/ebmc/k_induction.cpp index 9123617d..189b76e7 100644 --- a/src/ebmc/k_induction.cpp +++ b/src/ebmc/k_induction.cpp @@ -170,16 +170,39 @@ Function: k_inductiont::operator() void k_inductiont::operator()() { + // Unsupported assumption? Mark as such. + bool assumption_unsupported = false; + for(auto &property : properties.properties) + { + if(!supported(property) && property.is_assumed()) + { + assumption_unsupported = true; + property.failure("assumption unsupported by k-induction"); + } + } + // Fail unsupported properties for(auto &property : properties.properties) { - if(!supported(property)) + if(!supported(property) && !property.is_assumed()) property.failure("property unsupported by k-induction"); } // do induction base induction_base(); + // Any refuted properties are really inconclusive if there are + // unsupported assumptions, as the assumption might have + // proven the property. + if(assumption_unsupported) + { + for(auto &property : properties.properties) + { + if(property.is_refuted()) + property.unknown(); + } + } + // do induction step induction_step(); } diff --git a/src/ebmc/property_checker.cpp b/src/ebmc/property_checker.cpp index 39b5ee9c..13b43017 100644 --- a/src/ebmc/property_checker.cpp +++ b/src/ebmc/property_checker.cpp @@ -384,12 +384,13 @@ property_checker_resultt engine_heuristic( k_induction( 1, transition_system, properties, solver_factory, message_handler); - properties.reset_failure_to_unknown(); + properties.reset_failure(); if(!properties.has_unknown_property()) return property_checker_resultt{properties}; // done // Now try BMC with bound 5, word-level + message.status() << "Attempting BMC with bound 5" << messaget::eom; bmc( 5, // bound @@ -400,7 +401,7 @@ property_checker_resultt engine_heuristic( solver_factory, message_handler); - properties.reset_failure_to_unknown(); + properties.reset_failure(); if(!properties.has_unknown_property()) return property_checker_resultt{properties}; // done diff --git a/src/ebmc/property_checker.h b/src/ebmc/property_checker.h index d1fe7f00..bd59e6b8 100644 --- a/src/ebmc/property_checker.h +++ b/src/ebmc/property_checker.h @@ -50,12 +50,18 @@ class property_checker_resultt bool all_properties_proved() const { for(const auto &p : properties) - if( + { + if(p.is_assumption()) + { + // ignore + } + else if( !p.is_proved() && !p.is_proved_with_bound() && !p.is_disabled() && !p.is_assumed()) { return false; } + } return true; }