@@ -17,6 +17,7 @@ Author: Daniel Kroening, kroening@kroening.com
1717#include < util/symbol_table.h>
1818
1919#include < ebmc/ebmc_error.h>
20+ #include < temporal-logic/nnf.h>
2021#include < temporal-logic/temporal_expr.h>
2122#include < temporal-logic/temporal_logic.h>
2223#include < verilog/sva_expr.h>
@@ -511,106 +512,23 @@ static obligationst property_obligations_rec(
511512 // We need NNF, try to eliminate the negation.
512513 auto &op = to_not_expr (property_expr).op ();
513514
514- if (op.id () == ID_U)
515- {
516- // ¬(φ U ψ) ≡ (¬φ R ¬ψ)
517- auto &U = to_U_expr (op);
518- auto R = R_exprt{not_exprt{U.lhs ()}, not_exprt{U.rhs ()}};
519- return property_obligations_rec (R, current, no_timeframes);
520- }
521- else if (op.id () == ID_R)
522- {
523- // ¬(φ R ψ) ≡ (¬φ U ¬ψ)
524- auto &R = to_R_expr (op);
525- auto U = U_exprt{not_exprt{R.lhs ()}, not_exprt{R.rhs ()}};
526- return property_obligations_rec (U, current, no_timeframes);
527- }
528- else if (op.id () == ID_G)
529- {
530- // ¬G φ ≡ F ¬φ
531- auto &G = to_G_expr (op);
532- auto F = F_exprt{not_exprt{G.op ()}};
533- return property_obligations_rec (F, current, no_timeframes);
534- }
535- else if (op.id () == ID_F)
536- {
537- // ¬F φ ≡ G ¬φ
538- auto &F = to_F_expr (op);
539- auto G = G_exprt{not_exprt{F.op ()}};
540- return property_obligations_rec (G, current, no_timeframes);
541- }
542- else if (op.id () == ID_X)
543- {
544- // ¬X φ ≡ X ¬φ
545- auto &X = to_X_expr (op);
546- auto negX = X_exprt{not_exprt{X.op ()}};
547- return property_obligations_rec (negX, current, no_timeframes);
548- }
549- else if (op.id () == ID_implies)
550- {
551- // ¬(a->b) --> a && ¬b
552- auto &implies_expr = to_implies_expr (op);
553- auto and_expr =
554- and_exprt{implies_expr.lhs (), not_exprt{implies_expr.rhs ()}};
555- return property_obligations_rec (and_expr, current, no_timeframes);
556- }
557- else if (op.id () == ID_and)
558- {
559- auto operands = op.operands ();
560- for (auto &op : operands)
561- op = not_exprt{op};
562- auto or_expr = or_exprt{std::move (operands)};
563- return property_obligations_rec (or_expr, current, no_timeframes);
564- }
565- else if (op.id () == ID_or)
566- {
567- auto operands = op.operands ();
568- for (auto &op : operands)
569- op = not_exprt{op};
570- auto and_expr = and_exprt{std::move (operands)};
571- return property_obligations_rec (and_expr, current, no_timeframes);
572- }
573- else if (op.id () == ID_not)
515+ auto op_negated_opt = negate_property_node (op);
516+
517+ if (op_negated_opt.has_value ())
574518 {
575519 return property_obligations_rec (
576- to_not_expr (op).op (), current, no_timeframes);
577- }
578- else if (op.id () == ID_sva_until)
579- {
580- // ¬(φ W ψ) ≡ (¬φ strongR ¬ψ)
581- auto &W = to_sva_until_expr (op);
582- auto strong_R = strong_R_exprt{not_exprt{W.lhs ()}, not_exprt{W.rhs ()}};
583- return property_obligations_rec (strong_R, current, no_timeframes);
520+ op_negated_opt.value (), current, no_timeframes);
584521 }
585- else if (op. id () == ID_sva_s_until )
522+ else if (is_temporal_operator (op) )
586523 {
587- // ¬(φ U ψ) ≡ (¬φ R ¬ψ)
588- auto &U = to_sva_s_until_expr (op);
589- auto R = R_exprt{not_exprt{U.lhs ()}, not_exprt{U.rhs ()}};
590- return property_obligations_rec (R, current, no_timeframes);
591- }
592- else if (op.id () == ID_sva_until_with)
593- {
594- // ¬(φ R ψ) ≡ (¬φ U ¬ψ)
595- // Note LHS and RHS are swapped.
596- auto &until_with = to_sva_until_with_expr (op);
597- auto R = R_exprt{until_with.rhs (), until_with.lhs ()};
598- auto U = sva_until_exprt{not_exprt{R.lhs ()}, not_exprt{R.rhs ()}};
599- return property_obligations_rec (U, current, no_timeframes);
600- }
601- else if (op.id () == ID_sva_s_until_with)
602- {
603- // ¬(φ strongR ψ) ≡ (¬φ W ¬ψ)
604- // Note LHS and RHS are swapped.
605- auto &s_until_with = to_sva_s_until_with_expr (op);
606- auto strong_R = strong_R_exprt{s_until_with.rhs (), s_until_with.lhs ()};
607- auto W =
608- weak_U_exprt{not_exprt{strong_R.lhs ()}, not_exprt{strong_R.rhs ()}};
609- return property_obligations_rec (W, current, no_timeframes);
524+ throw ebmc_errort () << " failed to make NNF for " << op.id ();
610525 }
611526 else
527+ {
528+ // state formula
612529 return obligationst{
613530 instantiate_property (property_expr, current, no_timeframes)};
531+ }
614532 }
615533 else
616534 {
0 commit comments